Dynamic JS table

This table allows you to

by dzul1983

HTML

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script>
<script src="http://www.appelsiini.net/download/jquery.jeditable.mini.js"></script>
<div class="test-area">
    <button id="addNew">New Category</button>
    <table id="categoryTable" title="Cookie categories">
        <thead>
            <tr>
                <th data-prop-name="Name">Name</th>
                <th data-prop-name="Description">Description</th>
                <th data-prop-name="Values" data-prop-type="array">Values</th>
                <th data-prop-name="Enabled" data-prop-type="bool">Enabled</th>
                <th data-prop-type="delete">Delete</th>
            </tr>
        </thead>
        <tbody>
            
        </tbody>
    </table>
    <h4>Data</h4>
    <textarea id="dataSrc">[{"Name":"Lorem","Description":"Lorem ipsum dolor sit","Values":["lorem","ipsum","dolor","sit"],"Enabled":true},{"Name":"Heroes","Description":"List of heroes","Values":["Superman","Ironman","Thor"],"Enabled":false},{"Name":"Cars","Description":"List of cars","Values":["Nissan GTR","Ferrari Enzo"],"Enabled":false},{"Name":"Games","Description":"List of games","Values":["Battlefield 3","Gears of War","Call of Duty"],"Enabled":true}]</textarea>
    <button id="buildFromJson">Build</button>
</div>

CSS

.test-area {
    min-height: 200px;
}

table {
    border: 1px solid #000;
    border-collapse: collapse;
}

table thead {
    background-color: #f4f4f4;
    border-bottom: 1px solid #000;
}

table tbody tr:nth-child(even) {
    background-color: #c8c8c8;
}

table th:nth-child(1) {
    width: 100px
}

table th:nth-child(2) {
    width: 200px
}

table th:nth-child(3) {
    width: 300px
}

table th:nth-child(4) {
    width: 50px
}

.ui-sortable tr {
    cursor: n-resize;
}

#dataSrc {
    width: 500px;
    height: 150px;
}

JavaScript

function CategoryTable(options) {
    this.$table = $('#categoryTable');
    this.columns = $.map(this.$table.find('thead th'), function(value, index) {
        var $column = $(value);
        
        return {
            $element: $column,
            propName: $column.data('prop-name'),
            propType: $column.data('prop-type') || 'string'
        };
    });
    this.options = $.extend({}, options);
    this.init();
}

CategoryTable.prototype = {
    init: function () {
        var self = this;
        
        //self.buildData();
        self.makeSortable();
        self.makeEditable();
        
        if(self.options.addNewBtn) {
            self.options.addNewBtn.click(function(e) {
                e.preventDefault();
                self.addRow();
            });
        }
        
        var deleteColumns = $.grep(self.columns, function(item, index) {
            return item.propType === 'delete';
        });
        $.each(deleteColumns, function(i) {
            var index = self.columns.indexOf(deleteColumns[i]);
            self.$table.delegate('tbody td:nth-child(' + (index + 1) + ') a', 'click', function(e) {
                e.preventDefault();
                self.deleteRow($(this).closest('tr'));
            });
        });
        
        var boolColumns = $.grep(self.columns, function(item, index) {
            return item.propType === 'bool';
        });
        $.each(boolColumns, function(i) {
            var index = self.columns.indexOf(boolColumns[i]);
            self.$table.delegate('tbody td:nth-child(' + (index + 1) + ') input[type="checkbox"]', 'change', function(e) {
                self.buildData();
            });
        });
    },

    getCellType: function ($cell) {
        var $rowCells = $cell.closest('tr').find('td');
        var index = $rowCells.index($cell);

        return this.columns[index].propType || 'string';
    },

    buildData: function () {
        var self = this,
            data = [],
            rows...