Custom sorting in Datatable

My datatable was acting cool and all until I added a link to each integer element of a particular column. All of a sudden the sorting feature was acting weird.

Before I had something like this

  23

After adding a link, I have

  23

It turns out after I added the links, the default sorting function is treating everything as string. So to fix that I will need to add custom sort function to explicitly tell datatable how I want to do my sorting.

jQuery.fn.dataTableExt.oSort['intComparer-asc'] = function (a, b) {
	var m = a.match(/^\<.*\>(\d+)\<.*\>/);
	a = m[1];
	var m = b.match(/^\<.*\>(\d+)\<.*\>/);
	b = m[1];
	var value1 = parseInt(a);
	var value2 = parseInt(b);
	return ((value1 < value2) ? -1 : ((value1 > value2) ? 1 : 0));
};

jQuery.fn.dataTableExt.oSort['intComparer-desc'] = function (a, b) {
	var m = a.match(/^\<.*\>(\d+)\<.*\>/);
	a = m[1];
	var m = b.match(/^\<.*\>(\d+)\<.*\>/);
	b = m[1];
	var value1 = parseInt(a);
	var value2 = parseInt(b);
	return ((value1 < value2) ? 1 : ((value1 > value2) ? -1 : 0));
};
	
$(document).ready(function() {
	$('#my_datatable').each( function(){
		oTable = $(this).dataTable({
			'bPaginate': false, 
			'bInfo': false,
			'bFilter': false,
			'aoColumnDefs': [
				{ 'sType': 'intComparer', 'aTargets': [ 0, 1 ] }
			]
		});
	});
});

The key part is the line “{ ‘sType’: ‘intComparer’, ‘aTargets’: [ 0, 1 ] }“. As you can see, I have my first column and second column assigned to this custom new data type called intComparer. And intComparer-asc and intComparer-desc will take care of the sorting details.

jeditable textile textarea renderer issue

If you have ever played with jeditable, eventually you will get to this issue, which is dealing with the textarea. The Textile renderer on the official jeditable demo page works perfectly fine, but when I tried it I experienced quite some difficulty.

Basically the text I enter would NOT be what I see after pressing the ok button, due to the html rendering of the newline character. I found a lot of people sharing their pain all over the internet:

http://stackoverflow.com/questions/5277800/jeditable-handling-output-that-has-line-breaks
http://forum.jquery.com/topic/jeditable-jquery-question-regarding-textarea

After quite some time hacking around (especially on that demo page and its source), I finally got it working that way it’s supposed to be. Here is my solution.

First, your save and load php scripts should be doing what they have been doing. No change at all. Just make sure you have clean data in the database.

Second, in your page.php file (which renders your textarea), call a string replace function to change all substring “\n” to “<br>\n”. Below is the PHP code. It will give you the good initial values, rendered correctly by your browser.

$s = str_replace("\n", "
\n", $s);



Third, add the following callback to your .editable attribute list. Basically, on the client side it renders the line breaks for you.

callback: function(value, settings) { 
	var retval = value.replace(/\n/gi, "
\n"); $(this).html(retval); }

So it looks something like the following:

$('.editable_textile').editable('save.php', { 
    indicator : '',
    loadurl   : 'load.php',
    type      : 'textarea',
    submit    : 'OK',
    callback: function(value, settings) { 
	var retval = value.replace(/\n/gi, "
\n"); $(this).html(retval); }, cancel : 'Cancel', });

Then you are done! Hope this can save you some time. 😉

jquery datepicker date format

If you are using the jquery datepicker and have been displaying the date in the usual mysql date format, you probably will find it annoying that the date picker gives you the slash date format back. Here is how to keep the mysql date dash format all throughout.

var queryDate = '2012-01-10',
    dateParts = queryDate.match(/(\d+)/g)
    realDate = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);  
                                    // months are 0-based!

$('#datePicker').datepicker({ dateFormat: 'yy-mm-dd' }); // format to show
$('#datePicker').datepicker('setDate', realDate);

The code above will translate the mysql date to do the initial setup, then use the dash format for the text field.

Ref: http://stackoverflow.com/questions/1953840/datepickersetdate-issues-in-jquery

dataTables editable plugin multiple select

If you are using the jQuery datatable with the editable extension, you probably know that you can only highlight one single row (tr). In my opinion, that’s really for the purpose of integrating the single row add/delete functions.

If you need to implement multiple row operations, thus needing multiple row selection, here is how you can do it:

  1. Open up jquery.dataTables.editable.js
  2. Toward the end of the file, look for

    $(oTable.fnSettings().aoData).each(function () {
        $(this.nTr).removeClass(properties.sSelectedRowClass);
    });

  3. Comment that out.

Obviously by doing this we are breaking the single row add/del feature. So, you will need to make sure you are not using the builtin add/del buttons, namely btnAddNewRow and btnDeleteRow.

Now, how to grab the highlighted rows? If you follow the user manual, each of your tr should have an ID.

$('#myTable_id .row_selected').each(function () {
	item_id = this.id;
	// then do something with this id
});

Whatever you do, consider refreshing your table or the whole page to reflect the latest table content.

Disallow de-select when select-all is checked

Very often we need to present many checkboxes, and there is one additional checkbox for select-all. The html code is somewhat like the following:

Select All
1
2
3
4

Notice I name the js function toggle_selection because you may actually make it toggle later on.

Then, to enable the usual select-all action, this is the code:

function toggle_selection(){
	$("input[name='opt[]']").each(function (index, el)
	{
		if ($("#my_select_all").is(":checked")) $(el).attr("checked", "checked");
	});
}

Straightforward.

If you want to make the select-all checkbox toggle, change the if statement to the following:

		if ($("#my_select_all").is(":checked")) $(el).attr("checked", "checked");
		else $(el).removeAttr("checked");

Now, how do we disallow the de-select when select-all is checked? No problem, jQuery to the rescue!

jQuery().ready(function (){
	$("input[name='opt[]']").each(function(index, el) {
		$(this).change(function(){
			if ($("#my_select_all").is(":checked")) $(el).attr("checked", "checked");
		});
	});	
}

We are binding a onChange callback to each checkbox. Upon clicking, if our select-all checkbox is checked, our current checkbox will always be set to checked.

Don’t you love jQuery?

jQuery vs MooTools

If you are looking into learning javascript frameworks, this will likely be a question you will ask eventually. jQuery or MooTools? They are both very well known and well developed. By chance I came across this site http://jqueryvsmootools.com/ and I was quite impressed. The author did a pretty comprehensive analysis of these two frameworks. Good stuff! Be warned though, it’s quite a long read! 😉