yarek yarek - 3 months ago 6
CSS Question

How to show HTML Elements being sorted through animation

Here is my snippet :



.item {
display:inline-block;
width:120px;
height:120px;
border:1px solid red;
}

<div id="listing">
<div data-value="5" class="item">item 5</div>
<div data-value="3" class="item">item 3</div>
<div data-value="2" class="item">item 2</div>
<div data-value="1" class="item">item 1</div>
<div data-value="4" class="item">item 4</div>
</div>





I would like to sort the
div
s based on the value of the
data-value
attribute, but I want to show the items being rearranged using an animation. How can I do this?

Answer

Here's how you can animate the sort:

  1. Loop through all the elements and store their positions
  2. Position the elements absolutely at their original positions
  3. Get the position of the item that will be replaced, and animate to that position.
  4. (Optional) After the animation is complete, you may want to swap out the absolutely positioned items with regular items in sorted order, so the DOM order of the elements is correct.

function animateSort(parent, child, sortAttribute) {
  var promises = [];
  var positions = [];
  var originals = $(parent).find(child);
  var sorted = originals.toArray().sort(function(a, b) {
    return $(a).attr(sortAttribute) > $(b).attr(sortAttribute);
  });

  originals.each(function() {
    //store original positions
    positions.push($(this).position());
  }).each(function(originalIndex) {
    //change items to absolute position
    var $this = $(this);
    var newIndex = sorted.indexOf(this);
    sorted[newIndex] = $this.clone(); //copy the original item before messing with its positioning
    $this.css("position", "absolute").css("top", positions[originalIndex].top + "px").css("left", positions[originalIndex].left + "px");

    //animate to the new position
    var promise = $this.animate({
      top: positions[newIndex].top + "px",
      left: positions[newIndex].left + "px"
    }, 1000);
    promises.push(promise);
  });

  //instead of leaving the items out-of-order and positioned, replace them in sorted order
  $.when.apply($, promises).done(function() {
    originals.each(function(index) {
      $(this).replaceWith(sorted[index]);
    });
  });
}

$(function() {
  $("input").click(function() {
    animateSort("#listing", "div", "data-value");
  });
});
.item {
  display: inline-block;
  width: 120px;
  height: 120px;
  border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="button" value="Sort" />
<div id="listing">
  <div data-value="5" class="item">item 5</div>
  <div data-value="3" class="item">item 3</div>
  <div data-value="2" class="item">item 2</div>
  <div data-value="1" class="item">item 1</div>
  <div data-value="4" class="item">item 4</div>
</div>