Natural sort?

Natural sort?

hhmhhm Posts: 24Questions: 3Answers: 2
edited March 2009 in General
Are there plans to implement a natural sort like jTPS has it http://www.overset.com/2008/08/30/animated-sortable-datagrid-jquery-plugin-jtps/ ?
Or is there a plugin to achieve this?

Thanks, Hans

Replies

  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin
    Hi Hans,

    I've just added a small plug-in to the plug-ins page ( http://datatables.net/plug-ins#sorting_natrual ) which makes use of the excellent neutralSort() by Jim Palmer ( http://www.overset.com/2008/09/01/javascript-natural-sort-algorithm/ ).

    You could even replace DataTables' default sorting by altering the declaration to be: jQuery.fn.dataTableExt.oSort['string-asc'] :-)

    Hope this helps.
    Allan
  • hhmhhm Posts: 24Questions: 3Answers: 2
    Hi Allan,

    thanks for the feedback. Perhaps you remember: we had a conversation via email last year about this topic. But I ran into more than one snag here.

    The first one:
    Having a look at the examples I could not figure out how to follow your suggestion. I downloaded the code from Jim Palmer's website and saved it as a new file. Next step would be to include it in the header of my page after dataTables, right? What then?

    The second snag:
    I am realising the site with MODx: http://modxcms.com/ MODx is a CMS, that uses placeholders for code that is used more than once in a site. One sort of code blocks is called "snippets". MODx knows it hast to interpret a snippet, when some text is surrounded by a pair of double brackets like this: [[mySnippet]] See the documentation here: http://wiki.modxcms.com/index.php/Placeholders_used_by_MODx_Pages_and_Templates#Snippets_.28Samples.29

    While trying out to sort a table with aaSorting, I got a JavaScript error. MODx parses the initialisation code and finds "aaSorting": [[2,'desc']]. MODx removes the code between the [[ and the ]] and tries to find a snippet by this name. Since there is none and now the parameters are not more in the page, the browser can not run the JavaScript and display the table.

    Is there a way to escape or mask the brackets?

    I asked about this in the MODx user: forum http://modxcms.com/forums/index.php/topic,34001.msg206780.html#msg206780 to see if there is a way from the other side.

    Hans

    BTW: It would be really handy, if the forum would offer some kind of preview.
  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin
    Hi Hans,

    Indeed I do remember our conversation - natural sorting is a fantastic thing to have, and Jim Palmer's function is excellent at providing that in Javascript.

    1. So you've for the code for that sorting function - you also need the DataTable's plug-in code I linked to, and finally you need to tell the table which columns you want to use natural sorting on. Something like the following should do the trick. If you want all columns to be natural sorting you can override the default 'string' function in DataTables by changing the plug-in code to refer to "oSort['string-asc']" (and desc). Then you don't need to define the column types.

    [code]
    /*
    * Natural Sort algorithm for Javascript
    * Version 0.2
    * Author: Jim Palmer (based on chunking idea from Dave Koelle)
    * Released under MIT license.
    */
    function naturalSort (a, b) {
    // setup temp-scope variables for comparison evauluation
    var x = a.toString().toLowerCase() || '', y = b.toString().toLowerCase() || '',
    nC = String.fromCharCode(0),
    xN = x.replace(/([-]{0,1}[0-9.]{1,})/g, nC + '$1' + nC).split(nC),
    yN = y.replace(/([-]{0,1}[0-9.]{1,})/g, nC + '$1' + nC).split(nC),
    xD = (new Date(x)).getTime(), yD = (new Date(y)).getTime();
    // natural sorting of dates
    if ( xD && yD && xD < yD )
    return -1;
    else if ( xD && yD && xD > yD )
    return 1;
    // natural sorting through split numeric strings and default strings
    for ( var cLoc=0, numS = Math.max( xN.length, yN.length ); cLoc < numS; cLoc++ )
    if ( ( parseFloat( xN[cLoc] ) || xN[cLoc] ) < ( parseFloat( yN[cLoc] ) || yN[cLoc] ) )
    return -1;
    else if ( ( parseFloat( xN[cLoc] ) || xN[cLoc] ) > ( parseFloat( yN[cLoc] ) || yN[cLoc] ) )
    return 1;
    return 0;
    }

    jQuery.fn.dataTableExt.oSort['natural-asc'] = function(a,b) {
    return naturalSort(a,b);
    };

    jQuery.fn.dataTableExt.oSort['natural-desc'] = function(a,b) {
    return naturalSort(a,b) * -1;
    };

    $(document).ready( function() {
    $('#example').dataTable( {
    "aoColumns": [
    { "sType": "natural" },
    { "sType": "natural" },
    { "sType": "natural" }
    null
    ]
    } );
    } );
    [/code]




    2. aaSorting": [[2,'desc']] being removed by MODx

    Can't you just put spaces in-between the brackets? Remember white-space means nothing to Javascript, but I would imagine that MODx requires the brackets to be together.

    Allan
  • hhmhhm Posts: 24Questions: 3Answers: 2
    Hi Allan,

    both of your solutions are working. Thanks bunches. And: In the MODx forum I got an answer with the same solution.

    BTW: The project from last year has been axed shortly after our exchange and has been resurrected about 2 weeks ago. Since I don't use JavaScript for anything else this is the main reason why my skills using it haven't improved.

    Hans
  • AlanAbsentAlanAbsent Posts: 5Questions: 0Answers: 0
    Ive tried this code in many diffirent ways, and have been un successfull at getting it to work.. ive done everything said.. when sorting it wont sort number sin order at all say i have 7 6 22 56 ASC and then does 22 56 7 6 for DESC
    here the code
    [code]

    /*
    * Natural Sort algorithm for Javascript - Version 0.6 - Released under MIT license
    * Author: Jim Palmer (based on chunking idea from Dave Koelle)
    * Contributors: Mike Grier (mgrier.com), Clint Priest, Kyle Adams, guillermo
    */
    function naturalSort (a, b) {
    var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi,
    sre = /(^[ ]*|[ ]*$)/g,
    dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
    hre = /^0x[0-9a-f]+$/i,
    ore = /^0/,
    // convert all to strings and trim()
    x = a.toString().replace(sre, '') || '',
    y = b.toString().replace(sre, '') || '',
    // chunk/tokenize
    xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
    yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
    // numeric, hex or date detection
    xD = parseInt(x.match(hre)) || (xN.length != 1 && x.match(dre) && Date.parse(x)),
    yD = parseInt(y.match(hre)) || xD && y.match(dre) && Date.parse(y) || null;
    // first try and sort Hex codes or Dates
    if (yD)
    if ( xD < yD ) return -1;
    else if ( xD > yD ) return 1;
    // natural sorting through split numeric strings and default strings
    for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {
    // find floats not starting with '0', string or 0 if not defined (Clint Priest)
    oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
    oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
    // handle numeric vs string comparison - number < string - (Kyle Adams)
    if (isNaN(oFxNcL) !== isNaN(oFyNcL)) return (isNaN(oFxNcL)) ? 1 : -1;
    // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
    else if (typeof oFxNcL !== typeof oFyNcL) {
    oFxNcL += '';
    oFyNcL += '';
    }
    if (oFxNcL < oFyNcL) return -1;
    if (oFxNcL > oFyNcL) return 1;
    }
    return 0;
    }



    jQuery.fn.dataTableExt.oSort['string-asc'] = function(a,b) {
    return naturalSort(a,b);
    };

    jQuery.fn.dataTableExt.oSort['string-desc'] = function(a,b) {
    return naturalSort(a,b) * -1;
    };


    $(document).ready(function() {
    $('#theTable').dataTable( {
    "sPaginationType": "full_numbers",
    "aoColumnsDefs": [{ "sType": "natural" },
    { "sType": "natural" },
    { "sType": "natural" },
    null
    ]
    } );
    } );

    [/code]

    Any help would be awesome
  • AlanAbsentAlanAbsent Posts: 5Questions: 0Answers: 0
    edited June 2011
    ive also tried it this way

    [code]

    $(document).ready(function() {
    $('#theTable').dataTable( {
    "sPaginationType": "full_numbers",
    "aoColumnsDefs": [{ "sType": "natural" },
    { "sType": "natural" },
    { "sType": "natural" },
    null
    ]
    } );
    } );


    jQuery.fn.dataTableExt.oSort['string-asc'] = function(a,b) {
    return naturalSort(a,b);
    };

    jQuery.fn.dataTableExt.oSort['string-desc'] = function(a,b) {
    return naturalSort(a,b) * -1;
    };
    [/code]
This discussion has been closed.