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>
            <tr>
                <td>Lorem</td>
                <td>Lorem ipsum dolor sit</td>
                <td>lorem, ipsum, dolor, sit</td>
                <td><input type="checkbox" checked="checked" /></td>
                <td><a href="#">Delete</a></td>
            </tr>
            <tr>
                <td>Heroes</td>
                <td>List of heroes</td>
                <td>Superman, Ironman, Thor</td>
                <td><input type="checkbox" /></td>
                <td><a href="#">Delete</a></td>
            </tr>
            <tr>
                <td>Cars</td>
                <td>List of cars</td>
                <td>Nissan GTR, Ferrari Enzo</td>
                <td><input type="checkbox" /></td>
                <td><a href="#">Delete</a></td>
            </tr>
            <tr>
                <td>Games</td>
                <td>List of games</td>
                <td>Battlefield 3, Gears of War, Call of Duty</td>
                <td><input type="checkbox" checked="checked" /></td>
                <td><a href="#">Delete</a></td>
            </tr>
        </tbody>
    </table>
</div>
<strong>Data</strong>
<div id="output"></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;
}

JavaScript

function output(object) {
    $("#output").html(JSON.stringify(object));
}

function CategoryTable(options) {
    this.$table = $('#categoryTable');
    this.$columns = this.$table.find('thead th');
    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 deleteColumn = self.$columns.filter('[data-prop-type="delete"]');
        if(deleteColumn) {
            var index = self.$columns.index(deleteColumn);
            self.$table.delegate('tbody td:nth-child(' + (index + 1) + ') a', 'click', function(e) {
                e.preventDefault();
                self.deleteRow($(this).closest('tr'));
            });
        }
        
        var boolColumn = self.$columns.filter('[data-prop-type="bool"]');
        if(boolColumn) {
            var index = self.$columns.index(boolColumn);
            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]).data('prop-type') || 'string';
    },

    buildData: function () {
        var self = this,
            data = {},
            rows = self.$table.find('tr').not(':has(th)');

        $.each(self.$columns, function (index, value) {
            var $column = $(this);
            var key = $column.data('prop-name');
            var type = $column.data('prop-type');

            $.each(rows, function (_index, _value) {
                data[_index]...