Zorgan
Zorgan

Reputation: 9123

sort() sorts data by the first digit, not the whole number

I have a sorting method that I want to sort my divs based on their data-position attribute. At the moment, for some reason the function sorts the divs based only on the first digit, and not the whole number. Here is an example in my html which shows that:

html

<div class="parent" data-position="1">
    ...
</div>

<div class="parent" data-position="27">
    ...
</div>

<div class="parent" data-position="3">
    ...
</div>

Here's the js

$('body').on('click', '.new_comments', function(e) {
    var divArr = $(".parent");
    divArr.sort(function(a, b) {
        return $(a).attr('data-position') > $(b).attr('data-position') ? 1: -1;
    });
$(".comments_container").append(divArr);

});

Any idea why it does this and how to fix it?

Upvotes: 2

Views: 712

Answers (2)

user8897421
user8897421

Reputation:

Convert the string data to numbers.

$('body').on('click', 'button', function(e) {
  var divArr = $(".parent");
  
  divArr.sort(function(a, b) {
    return +$(a).attr('data-position') > +$(b).attr('data-position') ? 1 : -1;
  });

  $(".comments_container").append(divArr);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<button>CLICK ME</button>

<div class="comments_container">
  <div class="parent" data-position="1">
    1 </div> 
  <div class="parent" data-position="27">  27  </div> 
  <div class="parent" data-position="3"> 3 </div>
</div>

And I would first gather the attributes instead of doing it repeatedly in the callback.

$('body').on('click', 'button', function(e) {
  $(".parent")
    .map((i, el) => ({el: el, pos: +el.dataset.position}))
    .sort((a, b) => a.pos > b.pos ? 1 : -1)
    .map((i, {el}) => el)
    .appendTo(".comments_container");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<button>CLICK ME</button>

<div class="comments_container">
  <div class="parent" data-position="1"> 1 </div> 
  <div class="parent" data-position="27">  27  </div> 
  <div class="parent" data-position="3"> 3 </div>
</div>

I also included some modern syntax in this solution

Upvotes: 3

Taplar
Taplar

Reputation: 24965

$(a).attr('data-position')

Attr returns the attribute value as a string, so you're comparison is comparing strings, not numbers, which is what you are expecting I assume. Instead of using attr() use data().

$(a).data('position')

The difference between the two is that jQuery will try to auto convert the value in the attribute to a number if it can when you use data(). So with the values converted to numbers, you should see the sorting you expect.

Upvotes: 5

Related Questions