Snippets

Michael Riddle Editable Table jQuery UI Widget

Created by Michael Riddle last modified
$.widget('riddlemd.editableTable', {
    options : {
        sortable : false,
        fieldName : '',
        nextRowId : 0,
        autoAddNewRow : true,
        tbody : null,
        thead : null,
        values : []
    },
    // Private
    _create : function() {
        var currentWidget = this;
        
        currentWidget.options.thead = currentWidget.options.thead ? currentWidget.options.thead : currentWidget.element.children('thead');
        currentWidget.options.tbody = currentWidget.options.tbody ? currentWidget.options.tbody : currentWidget.element.children('tbody');

        currentWidget.element.addClass('editable-table');

        $.each(currentWidget.options.values, function() {
            currentWidget.addRow(this);
        });

        if(currentWidget.options.sortable) {
            currentWidget.options.tbody.sortable({
                items : 'tr:not(:last-child)',
                start : function(event, ui) {
                    ui.placeholder.height(ui.helper.outerHeight());
                }
            });
        }

        currentWidget.addRow({});
    },
    _getNextRowId : function() {
        var currentWidget = this;
        return currentWidget.options.nextRowId++;
    },
    // Public
    addRow : function(data) {
        var currentWidget = this;

        if(!data && !currentWidget.getLastRow().editableTableRow('isValid')) {
            return null;
        }

        data = data || {};

        data._rowId = currentWidget._getNextRowId();
        data._fieldName = currentWidget.options.fieldName;

        var $newRow = $('<tr>')
            .addClass('editable-table-row')
            .appendTo(currentWidget.options.tbody)
            .on('change', 'input', function(e) {
                var $currentInput = $(this);
                var $parentTr = $currentInput.closest('tr');
                currentWidget.onRowChanged({row:$parentTr});
                if(currentWidget.options.autoAddNewRow && $parentTr[0] == currentWidget.getLastRow()[0] && currentWidget.isRowValid($parentTr)) {
                    currentWidget.addRow({});
                }
            })
            .on('remove', function(e) {
                var $currentRow = $(this);
                currentWidget.onRowRemoved({row:$currentRow});
            });

        var event = currentWidget.onRowTemplateNeeded({row:$newRow,data:data});
        $newRow.append(event.html);

        this.onRowAdded({row:$newRow});

        return $newRow;
    },
    isRowValid : function(row)
    {
        var event = this.onRowValidating({row:$(row)});
        return event.valid;
    },
    getRows : function() {
        var currentWidget = this;
        var $rows = currentWidget.options.tbody.children();
        return $rows;
    },
    getLastRow : function() {
        var currentWidget = this;
        return currentWidget.getRows().last();
    },
    getFieldName : function() {
        var currentWidget = this;
        return currentWidget.options.fieldName;
    },
    removeInvalidRows : function() {
        var currentWidget = this;
        $.each(currentWidget.getRows(), function() {
            var $currentRow = $(this);
            if(!currentWidget.isRowValid($currentRow)) {
                $currentRow.remove();
            }
        });
    },
    // Events
    onTableSubmitted : function(args) {
        var event = jQuery.Event('tableSubmitted');
        $(this.element).trigger('tableSubmitted', [{rows:this.getRows()}]);
        return event;
    },
    onRowAdded : function(args) {
        var event = jQuery.Event('rowAdded');
        $(this.element).trigger(event, [args]);
        return event;
    },
    onRowRemoved : function(args) {
        var event = jQuery.Event('rowRemoved');
        $(this.element).trigger(event, [args]);
        return event;
    },
    onRowChanged : function(args) {
        var event = jQuery.Event('rowChanged');
        $(this.element).trigger(event, [args]);
        return event;
    },
    onRowValidating : function(args) {
        var event = jQuery.Event('rowValidating', { valid : true });
        $(this.element).trigger(event, [args]);
        return event;
    },
    onRowTemplateNeeded : function(args) {
        var event = jQuery.Event('rowTemplateNeeded', { html : ''});
        $(this.element).trigger(event, [args]);
        return event;
    }
});

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.