May 13, 2015
Legacy DataTable sorting with moment.js
Recently I had the requirement to add sorting to a legacy DataTables (1.7.5), the column contains data in [Monthname] YYYY
and DD.MM.YYYY – DD.MM.YYYY
format.
For example:
- December 2014
- 15.10.14-30.10.14
- January 2015
The normal DataTables sorting algorithm can only sort the column alphabetically, so we needed some improvement. After a short search on the DataTables website, I found this blog entry (http://datatables.net/blog/2014-12-18) with a plugin from Allan Jardin. The plugin can detect the date fields by a given pattern and then sort them with moment.js.
The problem here is, Allan Jardin wrote this plugin for the new DataTables API, so I first had to change the API-Calls to fit the legacy DataTables API. I changed following lines:
1 |
var types = $.fn.dataTable.ext.type; |
to
1 |
var types = $.fn.dataTableExt.aTypes; |
and
1 |
types.detect.unshift( function ( d ) |
to
1 |
types.unshift( function ( d ) |
The original implementation uses the -pre
sort name, this is available from DataTables 1.9+, so I splitted the implementation into -asc
and -desc
functions. Now you can add your desired date pattern to initialize the column sorting. With the line
1 |
$.fn.dataTable.moment( 'MMMM YYYY' ); |
prior to your DataTables initialization, the sorting is setup and ready to go. You can build your pattern with the help from the moment.js-docs.
Here you can find the code for Example 1.
With this implementation you can sort columns with the same date pattern, but our goal is to sort a column with mixed date patterns, as described above.
One one hand, we can use the pattern MMMM YYYY
mentioned above, but which pattern should we use for date-ranges?
In our implementation the dates are not overlapping, so I decided to use the first part of the date-range for sorting (15.10.14 - 30.10.14
-> 15.10.14
).
Therefore we got two moment.js patterns here:
MMMM YYYY
for December 2014DD.MM.YY
for 15.10.14
But we need the correct unix timestamp and the correct pattern for each entry,so I wrote wrote the getSpecialValueAndFormat
-Function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function getSpecialValueAndFormat(value) { //Remove tags, then remove \n and whitespaces value = value.replace ? value.replace(//g, '').replace(/(\r\n|\n|\r)/gm, '').trim() : value; if (/^[a-zA-Z]/.test(value.trim())) { return { value: value, format: "MMMM YYYY" }; } else { value = value.trim().split(" - ")[0]; return { value: value, format: "DD.MM.YY" }; } } |
- the function removes unused html-tags and whitespaces. (unfortunately generated by the Scala-Lift-Framework)
- based on a regex, the function decides which pattern should be used and returns the value and the correct pattern
With the value and the pattern, we can use the parseFormatToUnix
-Function from the first Example and calculate the timestamps.
Finally you only need to specify the sType
of the DataTables column with:
1 2 3 4 5 |
$('#table').dataTable({ "aoColumns": [{ sType: "custom-date" }] }); |
Here you can see the final code for Example 2.
I hope this helps thanks the moment.js-Team and Allan Jardin for his great plugin.