jQuery Datatables Plug-in

Filed in jQuery Leave a comment

I had to create some editable datatables and decided to give Datatables.net a try. It has tons of functionality and some great features. I read the documentation and tried a couple of test implementations and it seemed to work quite well. However, and this may be because of the way I think, it seemed to be missing a crucial concept when it comes to have many datatables. I DONT want to have to write an initialize block for every datatable that may happen to appear in my application. Thats a totally crap way of coding in my opinion.

You need to install the Datatables and Jeditable plugins for jQuery.

Here is how I defined the solution:

A table should become editable simply by adding some CSS classes and a couple of special attributes. The reason for all this is that I want to be able to define all the stuff for the table in one place.

  1. The table must have a unique ID
  2. The table must have a custom attribute off  ‘editURL’ with a value of the URL where the edit data will be sent
  3. Any column to be edited must have a class of ‘editable’
  4. The row containing the editable column must have an ID that the columns content can be tied to.
  5. The table must have a footer that contains a hidden row which is the template for new rows.

I know that custom HTML attributes can be a problem but I will use them in this case for two reasons. One is that the Datatables plugin adds it’s own and two this is a closed audience application so I have complete control.

Here is an example of the table HTML:

<table id="botnetDomainList" class="editable" editurl="/botnets/edit_domain">
    <thead>
        <tr>
	    <th>Domain</th>
	    <th class="control>Delete</th>
	</tr>
    </thead>
    <tbody>
        <tr id="cheeseburger.com">
	    <td class="editable ">cheeseburger.com</td>
	    <td><div class="deleteRow"></div></td>
	</tr>
    </tbody>
    <tfoot>
        <tr style="display:none;" class="template">
	    <td class="editable" style="">edit</td>
	    <td>
		<div class="deleteRow"></div>
	    </td>
	</tr>
	<tr>
	    <td></td>
	    <td>
	        <div class="addRow"></div>
	    </td>
	</tr>
    </tfoot>
</table>

Here is the Javascript that supports the tables. Once again my goal was to have to only write one Datatables Init function for all datatables. It may not cover some edge cases but it should work for majority. Read the comments to get details of what I did and why.

    $.add_field_edit_handlers = function(oTable){
        /*
             * Setup up the editable columns.
             * --The table must have an ID.
             * --The table must have a custom attribute of 'editURL' containing the url of
             *   where to send the edit data.
             * --The columns to be edited must have the class 'editable'
             * --The row containing the editable columns must have some sort of
             *   identifying information.
             */
        $('#' + oTable.attr('id') + ' td.editable').editable($(oTable).attr('editURL'), {
            "callback": function( sValue, y ) {
                /*
                 * Handle return from the server
                 */
                var aPos = $(oTable).dataTable().fnGetPosition( this );
                $(oTable).dataTable().fnUpdate( sValue, aPos[0], aPos[1] );
            },
            "submitdata": function ( value, settings ) {
                /*
                     * Sends to the server
                     */
                return {
                    "row_id": this.parentNode.getAttribute('id'),
                    "column": $(oTable).dataTable().fnGetPosition( this )[2]
                };
            }
        });
    }
    /**
     * Setup a generic editable datatable
     */
    $('table.editable').dataTable({
        "bPaginate": false,
        "bLengthChange": false,
        "bFilter": false,
        "bSort": false,
        "bInfo": false,
        "bAutoWidth": false,
        "fnInitComplete" : function(oSettings, json){
            var oTable = this;
            $.add_field_edit_handlers(oTable);
        }
    });
    /**
     * Add a click event handler to insert the hidden row template in the footer
     * into the tables body. This is sort of a pain in the ass due to the way that
     * the Datatables plugin works. You cant simply add your row. Datatables adds
     * rows by taking an array of cell content, not the cells themselves. This
     * means that our template row's cells lose their classes. So we have to extract
     * the classes and then add them back once Datatables.fnAddData() has added
     * the new row. swright 02-21-2012
     */
    $('.addRow').click(function(){
        // Get the ID of the clicked table
        var oTable = $(this).closest('table');
        // Something to hold the template row
        var template = new Array();
        // Something to hold the styles from each cell in the template row
        var td_class = new Array();
        /*
         * Iterate the TDs in the template row. Add the content for each cell to
         * the template array. Add the CSS class for each cell to the td_class array
         */
        $(oTable).find('tfoot tr.template td').each(function(){
            template.push($(this).html());
            if(typeof($(this).attr('class')) != "undefined"){
                td_class.push($(this).attr('class'));
            }
        });
        // Add the template array
        $(oTable).dataTable().fnAddData(template);
        /*
         * Iterate the new row's TDs and add the classes that we saved in the
         * td_class array.
         */
        $(oTable).find('tbody tr:last td').each(function(index, val){
            if(typeof(td_class[index]) != "undefined"){
                $(val).attr('class', td_class[index]);
            }
        });
        // Added the field edit handlers
        $.add_field_edit_handlers(oTable);
    });

TOP