81

If I have several divs:

<div data-sort='1'>div1</div>
<div data-sort='4'>div4</div>
<div data-sort='8'>div8</div>
<div data-sort='12'>div12</div>
<div data-sort='19'>div19</div>

And I dynamically create the divs:

<div data-sort='14'>div1</div>
<div data-sort='6'>div1</div>
<div data-sort='9'>div1</div>

How can I get them to just sort into the divs already loaded in order, without having to reload all of the divs?

I think that I would need to build an array of the data-sort values of all of the divs on the screen, and then see where the new divs fit in, but I am not sure if this is the best way.

brasofilo
  • 25,496
  • 15
  • 91
  • 179
TaylorMac
  • 8,882
  • 21
  • 76
  • 104

4 Answers4

120

Use this function

   var result = $('div').sort(function (a, b) {

      var contentA =parseInt( $(a).data('sort'));
      var contentB =parseInt( $(b).data('sort'));
      return (contentA < contentB) ? -1 : (contentA > contentB) ? 1 : 0;
   });

   $('#mylist').html(result);

You can call this function just after adding new divs.

If you want to preserve javascript events within the divs, DO NOT USE html replace as in the above example. Instead use:

$(targetSelector).sort(function (a, b) {
    // ...
}).appendTo($container);
Jess
  • 23,901
  • 21
  • 124
  • 145
Jayantha Lal Sirisena
  • 21,216
  • 11
  • 71
  • 92
  • seems to not like that last row: return (contentA <> contentB) ? 1 : 0; – TaylorMac May 26 '11 at 05:00
  • It's the "<>" that's the issue - I think that's the PHP "not equal to" operator. You'd want to use javascript's equivalent, which is "!=", or "!==" if you want stricter checking. See http://www.devguru.com/technologies/ecmascript/quickref/comparison_operators.html for notes on the difference between the two. – jszpila May 26 '11 at 06:16
  • awesome. I will try it out asap – TaylorMac May 27 '11 at 00:27
  • 19
    This seems to have a subtle bug because it uses `.attr('data-sort')` instead of `.data('sort')`. If the data-sort values are updated dynamically on the page, attr('data-sort') still uses the original values. – apb Sep 15 '13 at 21:35
  • 1
    @AndyB. Are you sure? Can you provide an example/version where this occurs? I tested here and it works fine: http://jsfiddle.net/fMe7R/1/ – danronmoon Oct 01 '13 at 12:30
  • 2
    @danronmoon ah yeah you're right - turns out I was setting with `.attr` and then trying to access with `.data` which are two different things. – apb Oct 03 '13 at 04:06
  • 3
    Works perfect. I used it to sort a bunch of UL elements containing terms. `$("#allTerms>ul").sort(function(a, b) { var contentA = parseInt($(a).attr('data-sort')); var contentB = parseInt($(b).attr('data-sort')); return (contentA < contentB) ? -1 : (contentA > contentB) ? 1 : 0; }).appendTo($("#allTerms"));` – Magali Jun 24 '15 at 08:24
  • Lotta people answered this topic in different threads. Yours works! Thanks much – ALFmachine Jan 14 '16 at 02:21
  • 17
    Just a gotcha for the example here. The sort method just returns the sorted list, it doesnt sort the elements in place. You need to manually add the new list by e.g. using $('#mylist').html(result); – Johncl Jul 03 '17 at 09:15
  • @JoaoPaulo, you can do it by interchanging greater than and lower than signs . – Jayantha Lal Sirisena Sep 25 '18 at 07:53
  • It's important to note that every time you use parseInt() you'll need to specify the radix to 10 (for normal decimal integers) like so: `parseInt( $(a).attr('data-sort'), 10)` https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt – Benjamin Dec 09 '19 at 13:42
  • 1
    How can this answer have 100 up votes and not actually work? You have to read all the comments to actually get the correct code... – Jess Jan 09 '20 at 21:49
  • Thanks for fixing it. – Jayantha Lal Sirisena Jan 10 '20 at 04:12
30

I made this into a jQuery function:

jQuery.fn.sortDivs = function sortDivs() {
    $("> div", this[0]).sort(dec_sort).appendTo(this[0]);
    function dec_sort(a, b){ return ($(b).data("sort")) < ($(a).data("sort")) ? 1 : -1; }
}

So you have a big div like "#boo" and all your little divs inside of there:

$("#boo").sortDivs();

You need the "? 1 : -1" because of a bug in Chrome, without this it won't sort more than 10 divs! http://blog.rodneyrehm.de/archives/14-Sorting-Were-Doing-It-Wrong.html

PJ Brunet
  • 3,615
  • 40
  • 37
  • 2
    I have a question to @PJBrunets solution. What happens to the divs previously located within the parent div? As far as I understand the solution, aren't we just adding more and more (sorted) divs to the parent? Don't we have to remove the 'old' divs? – Michaela.Merz Mar 09 '14 at 20:18
  • 1
    @Michaela.Merz I think they are sorted in place, no need to delete anything. But it has been a while since I created the function, I don't remember the details. I was using this with a hacked jquery.vgrid like this $("#grid-content").sortDivs(); window.vg = $("#grid-content").vgrid(); – PJ Brunet Mar 10 '14 at 18:27
  • 2
    Replace data("sort") with attr("data-sort") if you have dynamic data-sort attributes. Works well! – dxlliv Jul 01 '15 at 22:56
  • 1
    @Michaela.Merz old comment but for reference: the elements aren't copied when using the sort function, so when using appendTo, it **moves** the elements in the same `div` they are already in, resulting in an in-place sort. – Gugu72 Aug 25 '23 at 07:51
12

Answered the same question here:

To repost:

After searching through many solutions I decided to blog about how to sort in jquery. In summary, steps to sort jquery "array-like" objects by data attribute...

  1. select all object via jquery selector
  2. convert to actual array (not array-like jquery object)
  3. sort the array of objects
  4. convert back to jquery object with the array of dom objects

Html

<div class="item" data-order="2">2</div>
<div class="item" data-order="1">1</div>
<div class="item" data-order="4">4</div>
<div class="item" data-order="3">3</div>

Plain jquery selector

$('.item');
[<div class="item" data-order="2">2</div>,
 <div class="item" data-order="1">1</div>,
 <div class="item" data-order="4">4</div>,
 <div class="item" data-order="3">3</div>
]

Lets sort this by data-order

function getSorted(selector, attrName) {
    return $($(selector).toArray().sort(function(a, b){
        var aVal = parseInt(a.getAttribute(attrName)),
            bVal = parseInt(b.getAttribute(attrName));
        return aVal - bVal;
    }));
}
> getSorted('.item', 'data-order')
[<div class="item" data-order="1">1</div>,
 <div class="item" data-order="2">2</div>,
 <div class="item" data-order="3">3</div>,
 <div class="item" data-order="4">4</div>
]

See how getSorted() works.

Hope this helps!

Jeromy French
  • 11,812
  • 19
  • 76
  • 129
Troy Grosfield
  • 2,133
  • 20
  • 19
1

I used this to sort a gallery of images where the sort array would be altered by an ajax call. Hopefully it can be useful to someone.

var myArray = ['2', '3', '1'];
var elArray = [];

$('.imgs').each(function() {
    elArray[$(this).data('image-id')] = $(this);
});

$.each(myArray,function(index,value){
   $('#container').append(elArray[value]); 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div id='container'>
   <div class="imgs" data-image-id='1'>1</div>
   <div class="imgs" data-image-id='2'>2</div>
   <div class="imgs" data-image-id='3'>3</div>
</div>

Fiddle: http://jsfiddle.net/ruys9ksg/

Grant
  • 5,709
  • 2
  • 38
  • 50