jQuery tablesorter – Localized dates and numbers
At Kraftvaerk we have been using the jQuery tablesorter plugin in many of our projects. In most of these we have had to deal with localized dates and numbers in the tables. Ie a custom date format such as “25 jan 2010″ where the month name is localized, or a localized number with different thousand and decimal separator like “13.450,50″, or it could a totally custom display of weight like “200 Ton 352 Kg”.
How do you parse such strings with a custom jQuery tablesorter parser plugin in Javascript? The short is answer: You don’t, it simply requires too much work to maintain both the Javascript code and the server side code, in our case C#, that handles the formatting/parsing.
Instead you should include a sortable value, an integer, a decimal, or a string, in each table cell. You could display the aforementioned custom weight format as:
Make sure you read the update below for very simple sorting on localized values without a custom textExtraction function.
<td> 200 Ton 352 Kg<span class="hidden">200.352</span> </td>
With CSS you can hide the span tag with:
span.hidden {
display: none;
}
Since “200.352″ is a simple decimal number that tablesorter can sort you just need to tell tablesorter to use this hidden value instead of the formatted text. Fortunately this is very easy using the textExtraction config option.
$("table.sortable").tablesorter({
sortList: [[0, 0]],
widgets: ['zebra'],
textExtraction: function(node) {
return $(node).find("span.hidden").text();
}
});
Using this code you will need to include hidden span for all table cells, even though its not really needed, ie for simple text values or integers. To be honest we dont really like the use of an extra span tag inside the table cell. So we decided to create a custom attribute on the td tag and sort by this value:
<td sortvalue="200.352"> 200 Ton 352 Kg </td>
And the jQuery tablesorter config code:
$("table.sortable").tablesorter({
sortList: [[0, 0]],
widgets: ['zebra'],
textExtraction: function(node) {
return node.getAttribute('sortvalue') || node.innerHTML;
}
});
This code will check for an attribute named “sortvalue” and if it doesn’t exist it will use the text in the table cell instead. Unfortunately because the “sortvalue” attribute is not defined in any HTML specification by W3C your pages will not be fully valid (X)HTML. However using the jQuery Metadata plugin you can inject arbitrary information into the “class” attribute on any element. If you haven’t noticed the tablesorter plugin allows you to use this feature, so you might already be using the metadata plugin.
The table cell:
<td class="{sortvalue: '200.352'}">
200 Ton 352 Kg
</td>
jQuery tablesorter config code:
$("table.sortable").tablesorter({
sortList: [[0, 0]],
widgets: ['zebra'],
textExtraction: function(node) {
return $(node).metadata().sortvalue || node.innerHTML;
}
});
Update – Very simple sorting on localized values
A reader, Mathias, pointed out that when using the technique with a hidden span tag, there is no need for a custom textExtraction function. This is because the default textExtraction method for jQuery tablesorter checks for any child nodes in each table cell, and if the cell contains any child elements it will use the innerHTML value for the first child node. Here’s a snip from the jQuery tablesorter source code:
if(config.textExtraction == "simple") {
if(node.childNodes[0] && node.childNodes[0].hasChildNodes()) {
t = node.childNodes[0].innerHTML;
} else {
t = node.innerHTML;
}
} else {
// Snip
}
So using the hidden span technique is very easy, just make sure that the element containing the sortable value is the first child element of the table cell. In my example above the span was the only child element since the raw text "200 Ton 352 Kg" is not considered a node in DOM.
I have discussed the this hidden span/element technique with a designer colleague, and we both agree that it does mess up the semantics of the table a bit. What you could do is to wrap the human readable value in an element too. Like
<td> <span class="machine">200.352</span> <span class="human">200 Ton 352 Kg</span> </td>
That would bring some semantics back. Thanks to Mathias for the very useful comment.
Af:
Andreas Gehrke
Kategorier: Teknologi
