Search code examples
datetablesorter

jQuery Tablesorter custom parser, sorting dates with default `-` when no date available


I have written custom parser to sort on dates in format: 23-jul-2014

        $.tablesorter.addParser({
        // set a unique id
        id: 'dates',
        is: function(s, table, cell) {
            // return false so this parser is not auto detected
            return false;
        },
        format: function(s, table, cell, cellIndex) {

            // capture groups for rearranging
            pattern = /(^\d{2})-([A-Z]{3})-(\d{4})/gi;
            parts = pattern.exec(s);

            date = parts[2]+" "+parts[1]+", "+parts[3];
            return date ? $.tablesorter.formatFloat((new Date(date).getTime() || ''), table) || s : s;
        },

        // set type, either numeric or text
        type: 'numeric'
        });

,but in some of my fields where date is missing, I have - literally.

When this occurs sorting stops working, because it does not recognize that as regex match.

How would I change my parser code, so that it still can sort on that column, just by ignoring such fields having -, and sorting on those which have the proper date as 23-jul-2014?

I tried replacing that last s in return date... statement, to something like 1-jan-1970 to provide default value for - fields, but that didn't help.


Solution

  • It isn't necessary to split out all the parts of the date. Just replacing the dash with a space will work (demo):

    $(function () {
        $.tablesorter.addParser({
            // set a unique id
            id: 'dates',
            is: function (s, table, cell) {
                // return false so this parser is not auto detected
                return false;
            },
            format: function (s, table, cell, cellIndex) {
                var date = new Date(s.replace(/-/g, ' '));
                return $.type(date) === 'date' ? $.tablesorter.formatFloat(date.getTime(), table) || s : s;
            },
            // set type, either numeric or text
            type: 'numeric'
        });
    
        $('table').tablesorter({
            theme: 'blue',
            widgets: ['zebra']
            // add headers option here or "sorter-dates" class to header
            // ,headers : { 6 : { sorter: 'dates' } }
        });
    });
    

    Update (from question in comment):

    The || s : s is code that has two different things going on.

    The first part || s really isn't necessary in this case since the formatFloat function will return the same value if it is not numeric. The two vertical bars mean "OR", so 0 || 'x' will result in 'x'. So when javascript encounters an "OR" this || that if the left part is determined to be "falsy" (has a value of undefined, null, an empty string or has a value of zero), it is replaced with the value on the right side.

    The second part is the ending of a ternary operator. Basically the format is:

    condition ? value_if_true : value_if_false;
    

    so in the above the function

    return $.type(date) === 'date' ? $.tablesorter.formatFloat(date.getTime(), table) || s : s;
    

    we are returning a ternary operator (only the condition matching part is returned):

    • The condition is $.type(date) === 'date', to make sure we have a date object
    • The value_if_true part is $.tablesorter.formatFloat(date.getTime(), table) || s
    • The value_if_false part is s

    The ternary operators can be nested and can be very confusing to read, so use them, but don't go nuts ;)