Sort divs in jQuery based on attribute 'data-sort'?
Asked Answered
A

4

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.

Appenzell answered 26/5, 2011 at 4:35 Comment(0)
C
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);
Codpiece answered 26/5, 2011 at 4:47 Comment(12)
seems to not like that last row: return (contentA <> contentB) ? 1 : 0;Appenzell
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 devguru.com/technologies/ecmascript/quickref/… for notes on the difference between the two.Zwickau
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.Langobardic
@AndyB. Are you sure? Can you provide an example/version where this occurs? I tested here and it works fine: jsfiddle.net/fMe7R/1Kovacs
@Kovacs ah yeah you're right - turns out I was setting with .attr and then trying to access with .data which are two different things.Langobardic
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"));Outstretched
Lotta people answered this topic in different threads. Yours works! Thanks muchDupleix
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);Horsewoman
@JoaoPaulo, you can do it by interchanging greater than and lower than signs .Codpiece
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) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Flyaway
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...Baryram
Thanks for fixing it.Codpiece
P
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

Prey answered 15/6, 2013 at 20:6 Comment(4)
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?Dd
@Dd 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();Prey
Replace data("sort") with attr("data-sort") if you have dynamic data-sort attributes. Works well!Smallpox
@Dd 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.Ouellette
U
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!

Unproductive answered 25/4, 2014 at 16:55 Comment(0)
D
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/

Dowdell answered 19/2, 2015 at 2:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.