1

I want to reorder my divs according to the data-position, I tried this but it doesn't work.

jQuery("#bout div.foot").sort(function(a, b) {
  var position = jQuery(this).attr("data-position");
  return parseInt(a.position) - parseInt(b.position);
}).each(function() {
  var elem = jQuery(this);
  elem.remove();
  jQuery(elem).appendTo("#bout");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container vendors" id="bout">
  <div class="col-md-6 foot" data-position="4">4</div>
  <div class="col-md-6 foot" data-position="3">3</div>
  <div class="col-md-6 foot" data-position="4">4</div>
  <div class="col-md-6 foot" data-position="1">1</div>
</div>
PЯINCƎ
  • 646
  • 10
  • 28

2 Answers2

11

You're using the this keyword in the sort() handler whereas you instead need to use the a and b element references in order to compare them. You can also use data() instead of attr() to return the attributes. This will also return an integer to negate the need for parseInt(). Once the elements are sorted you can just append() them to the container without the extra each() loop. Try this:

$("#bout div.foot").sort(function(a, b) {
  return $(a).data("position") - $(b).data("position");
}).appendTo("#bout");

// alternative #1
// $("#bout div.foot").sort((a, b) => $(a).data("position") - $(b).data("position")).appendTo("#bout");

// alternative #2
// $("#bout div.foot").sort((a, b) => a.dataset.position - b.dataset.position).appendTo("#bout");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container vendors" id="bout">
  <div class="col-md-6 foot" data-position="4">4</div>
  <div class="col-md-6 foot" data-position="3">3</div>
  <div class="col-md-6 foot" data-position="4">4</div>
  <div class="col-md-6 foot" data-position="1">1</div>
</div>

Note that the logic does not deal with duplicate values in the sort algorithm, so you will need to implement a secondary method of sorting, if required.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • Great, thanks for your time – PЯINCƎ Nov 28 '18 at 11:43
  • a small question, do you know how to add also the order by name exemple if i have `data-position` values: 1, 1, 1, 2, for the 4 divs, so it order them by name for the the first three then 2 Please ? – PЯINCƎ Nov 28 '18 at 11:49
  • That's what my final note mentions. You'll need to amend the logic to detect when the values match, then order by something else. [Here's](https://stackoverflow.com/q/6913512/519413) a question which covers how to do that. – Rory McCrossan Nov 28 '18 at 12:03
3

Without jQuery, using Array.from and conveniently wrapped in a reusable function:

function sortChildren(containerSelector, reverse) {
  const container = document.querySelector(containerSelector);
  const order = reverse ? -1 : 1;
  
  Array.from(container.children)
    .sort((a, b) => order * parseInt(a.dataset.position, 10) - order * parseInt(b.dataset.position, 10))
    .forEach(element => container.appendChild(element));
    
  // Note you could also conditionally use Array.reverse() instead of the order variable.
}

sortChildren('#container1');
sortChildren('#container2', true);
body {
  display: flex;
  margin: 0;
  font-family: monospace;
  justify-content: space-around;
  align-items: flex-start;
}

.container {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 3px solid black;
  margin: 16px 0 0;
}

.container > li {
  padding: 4px 16px;
}
<ul class="container" id="container1">
    <li data-position="4">4</li>
    <li data-position="3">3</li>
    <li data-position="4">4</li>
    <li data-position="1">1</li>
    <li data-position="6">6</li>
</ul>

<ul class="container" id="container2">
    <li data-position="1">1</li>
    <li data-position="2">2</li>
    <li data-position="3">3</li>
    <li data-position="4">4</li>
    <li data-position="5">5</li>
    <li data-position="6">6</li>
    <li data-position="7">7</li>
</ul>

As you can see, there's no need to remove the elements, as when they are appended they will automatically be moved from their previous position to the new one.

Danziger
  • 19,628
  • 4
  • 53
  • 83