Recently a customer pointed out that the tables we’re displaying on our account pages at WonderProxy sort incorrectly. The problem was pretty obvious: the sorting ignored units, so 102 MB > 2 GB as far as the sorting algorithm was concerned.
I considered a few ways to solve the problem: my first thought was to put the raw total (in bytes) in some sort of attribute of the <td> element containing the value I was sorting. That done, it would be trivial to instruct the table sorter to just use that value when sorting. Looking through the HTML spec I couldn’t find an appropriate attribute to add, and didn’t really feel comfortable shoe-horning it into title or even worse, id.
The solution I settled on (and there may be far wiser solutions) was to write a basic parser that pulls out the numeric value, then applies an appropriate multiplier to turn the values into megabytes.
The first change came in when I instantiated the table sorter: here I instruct it to parse the values with the textExtraction property.
$('#add_servers_table') .addClass('tablesorter') .tablesorter({ //This function reverses our pretty print stuff so that we sort 90MB vs 1GB correctly textExtraction: function(node) { var value = node.innerHTML; return parseTraffic(value); } });Next I whipped up a quick function that checks to see if the value does indeed look to be a traffic value (since I’ve just applied this globally it’s also parsing values like Vancouver or 24%). Then it determines which multiplier to apply, and applies it.
function parseTraffic(value) { if (value.slice(-1) != 'B') { return value; }else if(value.slice(-2) == 'MB') { value = parseInt(value.slice(0, -3), 10); return value; }else if(value.slice(-2) == 'GB') { value = parseInt(value.slice(0, -3), 10); return value * 1024; }else if(value.slice(-2) == 'TB') { value = parseInt(value.slice(0, -3), 10); return value * 1024 * 1024; }else if(value.slice(-2) == 'KB') { value = parseInt(value.slice(0, -3), 10); return value / 1024; }else if(value.slice(-2) == ' B') { value = parseInt(value.slice(0, -3), 10); return 0; } //I shouldn’t be? return value; }I’m open to better solutions, but comments are still broken. Feel free to contact me: @preinheimer on twitter or paul@preinheimer on the emails.