使用knockout.js表优化可编辑的项目

时间:2016-06-14 14:05:51

标签: knockout.js jeditable

我有一个使用knockout.js生成的项目表,然后我使用此代码使每行上的某些项目可编辑:

function setupDeliveryItemsTable() {
    //console.log('doing setupDeliveryItemsTable');
    $('#deliveryItemsTable').tablesorter({ widgets: ['zebra'], headers: { 4: { sorter: false } } });

    // Select field edit in places
    var fields = $("#deliveryItemsTable div[id^='edit_select-delivery_items-']").map(function() { return this.id; }).get();
    var options = {
        type: 'select',
        loadurl: SITE_URL + '/ajax.php?action=getDeliveryDriversJSON'
    };
    $.each(fields, function() {
        // Determine our settings
        var id = this;
        var table = id.replace(/edit_select-([a-zA-Z_]+?)-([0-9]+?)_(.*)/, '$1');
        var dbID  = id.replace(/edit_select-([a-zA-Z_]+?)-([0-9]+?)_(.*)/, '$2');
        var name  = id.replace(/edit_select-([a-zA-Z_]+?)-([0-9]+?)_(.*)/, '$3');

        var default_options = {
            id        : 'cssID',
            cancel    : '<button class="btn btn-default btn-sm editable-cancel" type="button"><i class="glyphicon glyphicon-remove"></i></button>',
            submit    : '<button class="btn btn-primary btn-sm editable-submit" type="submit"><i class="glyphicon glyphicon-ok"></i></button>',                     
            indicator : indicatorImage,
            tooltip   : 'Click to edit...',
            style     : 'display: inline;',
            width     : 'none'
        };
        options = $.extend({}, default_options, options);
        if ( options.loadurl ) { options.loadurl += '&id=' + dbID; }

        $('#' + id).addClass('editableItemHolder').editable( 
            SITE_URL + '/ajax.php?action=updateDeliveryDriverByID&id=' + dbID, 
            options
        );
    });

    var fields = $("#deliveryItemsTable div[id^='edit-delivery_items-']").map(function() { return this.id; }).get();
    options = {
        type: 'textarea',
    };
    addEditable( fields, options );
}

基本上,此代码对每行上的几个项目做出反应,如下所示:

<td><div id="edit-delivery_items-62_location">St 156 # 17 ( Phsa Depo )</div></td>
<td><div id="edit-delivery_items-62_notes">Not Pick up 20/05</div></td>
<td><div id="edit_select-delivery_items-62_delivered_by">Click to edit</div></td>

每次替换表的数据时,都会重新运行此代码。因此,如果执行搜索,则会更改表数据并重新运行setupDeliveryItemsTable()。

我遇到的问题是有大量行,这会大大减慢页面速度,有时会导致浏览器崩溃。

我可以做些什么来优化此代码,以便仍然允许可编辑的项目,而不会在服务器上如此困难。

我应该使用类似的东西:

$(document).on('click' 

检测点击应该是一个可编辑的字段,然后调用可编辑的函数并链接一个点击事件,还是有更好的方法?

1 个答案:

答案 0 :(得分:0)

感谢您的回复,我可以使用knockout.js点击处理程序进行一些更改。我还必须更改jeditable以使用按钮来触发可编辑事件。通常我使用jeditable来使所有表格都可编辑。 Jeditable在调用它时会这样做,它会处理所点击项目的点击事件。

这是我的最终HTML

<table class="table table-striped table-bordered table-hover tablesorter" id="deliveryItemsTable" data-bind="visible: showTable">
        <thead> 
            <tr class="title1">
                <td colspan="100%">Delivery Items</td>
            </tr>
            <tr class="title2">
                <th class="header">Created On</th>
                <th class="header">Company</th>
                <th class="header">Item Number</th>
                <th class="header">Phone Number</th>
                <th>Price</th>
                <th class="header">Location</th>
                <th class="header">Notes</th>
                <th class="header">Delivery Driver</th>
                <th class="header">Status</th>
                <th class="header nowrap"></th>
            </tr>
        </thead>
        <tbody data-bind="foreach: deliveryItems">
            <tr data-bind="attr: {id: 'row_' + id }">
                <td data-bind="text: created_on"></td>
                <td data-bind="text: company_name"></td>
                <td data-bind="text: product_number_company"></td>
                <td data-bind="text: client_phone_number"></td>
                <td data-bind="text: formatCurrency(price_to_display)"></td>
                <td>
                    <span data-bind="text: location, attr: {id: 'edit-delivery_items-' + id + '_location' }"></span>
                    <button data-bind="click: $root.editLocation" class="btn btn-default btn-xs" title="Edit"><i class="glyphicon glyphicon-edit"></i></button>
                </td>
                <td>
                    <span data-bind="text: notes, attr: {id: 'edit-delivery_items-' + id + '_notes' }"></span>
                    <button data-bind="click: $root.editNotes" class="btn btn-default btn-xs" title="Edit"><i class="glyphicon glyphicon-edit"></i></button>
                </td>
                <td>
                    <span data-bind="text: delivered_by_text, attr: {id: 'edit_select-delivery_items-' + id + '_delivered_by' }"></span>
                    <button data-bind="click: $root.editDeliveryDriver" class="btn btn-default btn-xs" title="Edit"><i class="glyphicon glyphicon-edit"></i></button>
                </td>                   
                <td data-bind="html: status_labels"></td>
                <td class="center"><span class="btn-group">
                    <button data-bind="click: $root.markAsDelivered, visible: $root.canMarkComplete" class="btn btn-default" title="Mark as delivered"><i class="glyphicon glyphicon-check"></i></button>
                    <a data-bind="attr: {href: 'index.php?action=editDeliveryItem&amp;id=' + id }, visible: $root.canEdit" class="btn btn-default" title="Edit"><i class="glyphicon glyphicon-edit"></i></a> 
                </span></td>
            </tr>
        </tbody>
    </table>
    <div class="alert alert-info" data-bind="visible: showLoadingNotice">
        Loading...
    </div>
    <div id="deliveryItemsTableUpdateNotice"></div>

这是我提出的处理表格和可编辑项目的JS:

var deliveryItemsModel = function () {
    var self = this;

    self.deliveryItems = ko.observableArray();
    self.showTable = ko.observable(false);
    self.showLoadingNotice = ko.observable(true);
    self.canMarkComplete = ko.observable(false);
    self.canEdit = ko.observable(false);

    self.getDeliveryItems = function () {           
        $.getJSON( SITE_URL + '/ajax.php?action=returnDeliveryItemsTableJSON', function(retrievedData) {
            self.updateData(retrievedData);
            //console.log('back out');
        });         
    };

    self.getDeliveryItemsForToday = function () {           
        var todaysDate = new Date();
        $.getJSON( SITE_URL + '/ajax.php?action=returnDeliveryItemsTableJSON&status=not-delivered&scheduled_for_delivery_on=' + (todaysDate.getMonth() + 1) + '/' + todaysDate.getDate() + '/' +  todaysDate.getFullYear(), function(retrievedData) {
            self.updateData(retrievedData);
            //console.log('back out');
        });         
    };

    self.updateData = function (data) {         
        self.deliveryItems(data);               

        self.showLoadingNotice(false);
        self.showTable(true);
        //console.log(data);

        // We moved this to functions.js since we use it multiple times
        setupDeliveryItemsTable();      
    };

    self.replaceData = function (data) {
        self.showLoadingNotice(true);
        self.showTable(false);  
        self.updateData(data);
    };

    /* Click Functions */
    self.markAsDelivered = function (deliveryItem) {
        bootbox.confirm('Are you sure you want to mark this as delivered?', function(result) {
            if ( result == true ) {
                self.showLoadingNotice(false);
                self.showTable(true);
                jQuery.post(SITE_URL + '/ajax.php?action=markDeliveryItemDelivered&id=' + deliveryItem.id, function(data) {
                    // Trigger the search function to refresh the table
                    $('#searchDeliveryItemsForm').submit();
                });
            }
        });
    };  

    self.editLocation = function (deliveryItem) {
        handleEditOnClick('delivery_items', deliveryItem.id, 'location');
    };
    self.editNotes = function (deliveryItem) {
        handleEditOnClick('delivery_items', deliveryItem.id, 'notes');
    };
    self.editDeliveryDriver = function (deliveryItem) {
        handleEditDeliveryDriverOnClick('delivery_items', deliveryItem.id, 'delivered_by');
    };
};

/* Functions we use for the model above */  
function handleEditOnClick(table, dbID, name) { 
    var options = {
        event     : 'edit',
        id        : 'cssID',
        cancel    : '<button class="btn btn-default btn-sm editable-cancel" type="button"><i class="glyphicon glyphicon-remove"></i></button>',
        submit    : '<button class="btn btn-primary btn-sm editable-submit" type="submit"><i class="glyphicon glyphicon-ok"></i></button>',                     
        indicator : indicatorImage,
        tooltip   : 'Click to edit...',
        style     : 'display: inline;',
        width     : 'none',
        type      : 'textarea'
    };

    $('#edit-' + table + '-' + dbID + '_' + name).editable( 
        SITE_URL + '/ajax.php?action=updateitem&table=' + table + '&item=' + name + '&id=' + dbID, 
        options
    ).trigger('edit');
};
function handleEditDeliveryDriverOnClick(table, dbID, name) {   
    var options = {
        event     : 'edit',
        id        : 'cssID',
        cancel    : '<button class="btn btn-default btn-sm editable-cancel" type="button"><i class="glyphicon glyphicon-remove"></i></button>',
        submit    : '<button class="btn btn-primary btn-sm editable-submit" type="submit"><i class="glyphicon glyphicon-ok"></i></button>',                     
        indicator : indicatorImage,
        tooltip   : 'Click to edit...',
        style     : 'display: inline;',
        width     : 'none',
        type      : 'select',
        loadurl   : SITE_URL + '/ajax.php?action=getDeliveryDriversJSON' + '&id=' + dbID
    };

    $('#edit_select-' + table + '-' + dbID + '_' + name).editable( 
        SITE_URL + '/ajax.php?action=updateDeliveryDriverByID&id=' + dbID, 
        options
    ).trigger('edit');
};

        var viewModel = new deliveryItemsModel();
        ko.applyBindings( viewModel );      

        viewModel.canMarkComplete(true);
        viewModel.canEdit(true);

        viewModel.getDeliveryItems();

我不确定这是否会对其他人有所帮助,但我认为我最终会分享对我有用的东西。

如果有人认为有任何方法可以进一步优化,请告诉我。