Bizarre sorting problem with 1.9.4 and jQuery 1.9

Bizarre sorting problem with 1.9.4 and jQuery 1.9

danhunterdanhunter Posts: 6Questions: 0Answers: 0
edited February 2013 in Bug reports
I've noticed a weird bug when using custom sorting with dataTables 1.9.4 and jQuery 1.9.

When using the text from the DOM to define the sort order, using something like the following:
[code]
$.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn, iVisColumn )
{
var aData = [];
$( 'td:eq('+iVisColumn+')', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
aData.push($(this).text());
} );
return aData;
};
[/code]

..things work fine with jQuery 1.8.2, but seemingly randomly with 1.9.1.

I setup a JSBin here: http://live.datatables.net/ivojev/edit#javascript,html and it works fine, as expected. However if I setup the same environment locally and use jQuery 1.9.1, the sorting on the appropriate content becomes erratic.

Not sure if this is a bug with jQuery 1.9's text method (though the output looks correct) or with the dataTables sorting.. or something in my setup.

Replies

  • allanallan Posts: 63,685Questions: 1Answers: 10,498 Site admin
    This appears to be due to a change in jQuery 1.9 in how the DOM nodes are ordered in a result set which contains disconnected nodes. Previously `each` would loop over the nodes in the order that they were given (i.e. the order from _fnGetTrNodes) which is what DataTables needed. However the jQuery 1.9 upgrade notes say:

    > Before 1.9, sets that contained some connected and some disconnected nodes would be sorted inconsistently, depending on whether a disconnected node led the original unsorted set. As of 1.9, connected nodes are always placed at the beginning of the set in document order, and disconnected nodes are placed behind them.

    That is also what DataTables wants, but doesn't appear to be what jQuery is doing - the disconnected nodes are actually inserted in the middle of the array, which is a bit odd. I think this is a bug in jQuery - I hope it is, as this is going to have a considerable knock on effect on me. I'll open a jQuery bug to see what they think about this.

    Until then, here is a rewrite of the plug-in you are using to address this: http://live.datatables.net/ivojev/2/edit

    [code]
    $.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn, iVisColumn )
    {
    var trs = oSettings.oApi._fnGetTrNodes(oSettings);

    return $.map( trs, function (tr, i) {
    return $('td:eq('+iVisColumn+')', tr).text();
    } );
    };
    [/code]

    Allan
  • danhunterdanhunter Posts: 6Questions: 0Answers: 0
    Thanks for looking into this so quickly Allan. Hopefully jQuery can fix the problem soon so it doesn't turn into too big of a problem for you.

    Appreciate the new plugin code too, it works like a charm. Thanks also for your considerable and continuing work on DataTables.
  • allanallan Posts: 63,685Questions: 1Answers: 10,498 Site admin
    With DataTables 1.10 it should be possible to do something like:

    [code]
    return this.column( visColumn ).data();
    [/code]

    which will make life easier.

    I presume you aren't just doing a text sort on the content though, but something a little more complex? Out of interest, what is that, if that is the case?

    Allan
  • danhunterdanhunter Posts: 6Questions: 0Answers: 0
    I'm using DataTables inside a Backbone app. The user is able to update multiple models at once, which automatically (such is the way of Backbone) updates the DOM elements in the table.

    I found that sorting, using a custom sort method which updates the internal data to match the DOM, to be the best way to update DataTables after the models are updated (thus enabling me to update the filters based on the DataTables data, etc.) Rather than passing back all the updated data and calling fnUpdate for each. Is there a better way of doing this?
  • allanallan Posts: 63,685Questions: 1Answers: 10,498 Site admin
    > Is there a better way of doing this?

    Not yet - there will be in 1.10 where you will be able to use specific properties / functions for each of the data types DataTables uses (filtering for example). You'd just specify where the sorting data is in the source object. You can sort of do this with mData as a function already, but there are other incompatibilities with Backbone and DataTables at the moment, which 1.10 should also resolve.

    Allan
  • danhunterdanhunter Posts: 6Questions: 0Answers: 0
    edited February 2013
    [quote]but there are other incompatibilities with Backbone and DataTables at the moment[/quote]

    ..this is true, though I've managed to get them working together quite happily, if a little redundantly. I used the following snippet that you suggested in another thread to provide the initial 'sync' with Backbone..

    [code]
    "fnCreatedRow": (nRow, aData, iDataIndex) ->
    p = new Bluebase.Views.Product({el: nRow, model: view.collection.get(aData[0])})
    [/code]

    ..and it's working pretty nicely so far. I look forward to seeing what 1.10 brings though (using a Backbone collection as the data source?)
  • allanallan Posts: 63,685Questions: 1Answers: 10,498 Site admin
    Ultimately yes, I hope a Backbone collection could be used as a data source, although it isn't a primary goal for 1.10. I'm hoping it will fall out of the other work though.

    Allan
  • allanallan Posts: 63,685Questions: 1Answers: 10,498 Site admin
    So a bit of further investigation into this - I've used these two test cases:

    No DataTables: http://live.datatables.net/uwidel/edit#source
    DataTables: http://live.datatables.net/ivojev/4/edit

    The new DataTables version shows that jQuery 1.9 is now always trying to order the nodes by document order, not but the order that they are found in the source array. Additionally removed nodes are appended to the results, themselves in reserve order, but that's just the way the Sizzle node ordering works when items are not in the document (try sorting numbers and you get the same result).

    Given the suggestion in the release notes that the move is to have nodes always treated in document order, I don't think this is a bug, so not filing one. It is a bit frustrating that the nodes are iterated in a different order from the source array, but it is expected from their documentation and comments. So this is simply something we'll need to work around.

    To that end, I've updated the examples and taken the unusual step of updating the examples on this site outside the normal release cycle. The examples in the 1.9.4 current release of DataTables can't change of course, but the updated examples will be in 1.10 when it is released.

    Commit: https://github.com/DataTables/DataTables/commit/e00037a1af
    Example: http://datatables.net/release-datatables/examples/plug-ins/dom_sort.html

    Allan
This discussion has been closed.