jQuery Sorting Children (300) (v4)

Revision 4 of this benchmark created on


Preparation HTML

<script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>

<ul id="alnum">
    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>zulu</li>
    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>

    <li>alpha</li>
    <li>golf</li>
    <li>hotel</li>
    <li>charlie</li>
    <li>bravo</li>
    <li>echo</li>
    <li>delta</li>
    <li>delta</li>
    <li>foxtrot</li>
</ul>

Setup

// clone source
  $('#alnum').clone().attr('id', 'testytesty').appendTo(document.body);
  
  
  // sortChildren 1
  $.fn.sortChildren_1 = function(compare) {
      var $children = this.children();
      $children.sort(compare || $.fn.sortChildren_1.compare);
      this.append($children);
      return this;
  };
  $.fn.sortChildren_1.compare = function(a, b) {
      var an = $(a).text().toLowerCase();
      var bn = $(b).text().toLowerCase();
      return an > bn ? 1 : -1;
  };
  
  // sortChildren 2 (skipping jQuery's append())
  $.fn.sortChildren_2 = function(compare) {
      return this.each(function(){
          var $children = $(this).children();
          $children.sort(compare || $.fn.sortChildren_2.compare);
          for (var i=0, l=$children.length; i < l ; i++) {
              this.appendChild($children[i]);
          }
      });
  };
  $.fn.sortChildren_2.compare = function(a, b) {
      var an = $(a).text().toLowerCase();
      var bn = $(b).text().toLowerCase();
      return an > bn ? 1 : -1;
  };
  
  // sortChildren 3 (sorting a map)
  $.fn.sortChildren_3 = function(mapper, compare) {
      return this.each(function() {
          var $children = $(this).children(),
              map = [],
              i, l;
      
          for (i=0, l=$children.length; i < l ; i++) {
              map.push([i, (mapper || $.fn.sortChildren_3.map)($children[i]) ]);
          }
                  
          map.sort(compare || $.fn.sortChildren_3.compare);
  
          for (i=0, l=map.length; i < l ; i++) {
              this.appendChild($children[map[i][0]]);
          }
      });
  };
  $.fn.sortChildren_3.map = function(a, b) {
      defaultMapper = function(elem) {
          return $(elem).text().toLowerCase();
      };
  };
  $.fn.sortChildren_3.compare = function(a, b) {
      return a[1] > b[1] ? 1 : -1;
  };
  
  // sortChildren 4 (sorting a map on detached dom)
  $.fn.phase = function() {
      return this.each(function() {
          var $this = $(this),
              placeholder = $this.data('redetach');
  
          if (placeholder) {
              placeholder.parentNode.replaceChild(this, placeholder);
              $this.removeData('redetach');
          } else {
              placeholder = document.createTextNode(''),
              this.parentNode.replaceChild(placeholder, this);
              $this.data('redetach', placeholder);
          }
      });
  };
  $.fn.sortChildren_4 = function(map, compare) {
      return this.each(function() {
          var $this = $(this).phase(),
              $children = $this.children(),
              _map = [],
              length = $children.length,
              i;
      
          for (i = 0; i < length ; i++) {
              _map.push([i, (map || $.fn.sortChildren_4.map)($children[i])]);
          }
                  
          _map.sort(compare || $.fn.sortChildren_4.compare);
  
          for (i = 0; i < length ; i++) {
              this.appendChild($children[_map[i][0]]);
          }
          
          $this.phase();
      });
  };
  $.fn.sortChildren_4.compare = function(a, b) {
      return a[1] > b[1] ? 1 : -1;
  };
  $.fn.sortChildren_4.map = function(elem) {
      return $(elem).text().toLowerCase();
  };
  
  // from http://james.padolsey.com/javascript/sorting-elements-with-jquery/
  jQuery.fn.sortElements = (function(){
   
      var sort = [].sort;
   
      return function(comparator, getSortable) {
   
          getSortable = getSortable || function(){return this;};
   
          var placements = this.map(function(){
   
              var sortElement = getSortable.call(this),
                  parentNode = sortElement.parentNode,
   
                  // Since the element itself will change position, we have
                  // to have some way of storing its original position in
                  // the DOM. The easiest way is to have a 'flag' node:
                  nextSibling = parentNode.insertBefore(
                      document.createTextNode(''),
                      sortElement.nextSibling
                  );
  
              return function() {
   
                  if (parentNode === this) {
                      throw new Error(
                          "You can't sort elements if any one is a descendant of another."
                      );
                  }
   
                  // Insert before flag:
                  parentNode.insertBefore(this, nextSibling);
                  // Remove flag:
                  parentNode.removeChild(nextSibling);
   
              };
   
          });
   
          return sort.call(this, comparator).each(function(i){
              placements[i].call(getSortable.call(this));
          });
   
      };
   
  })();

Teardown



            $('#testytesty').remove();
        
  

Test runner

Ready to run.

Testing in
TestOps/sec
sortElements()
$('#testytesty').children().sortElements(function(a, b){
    return $(a).text().toLowerCase() > $(b).text().toLowerCase() ? 1 : -1;
});
ready
sortChildren_1()
$('#testytesty').sortChildren_1();
ready
sortChildren_2()
$('#testytesty').sortChildren_2();
ready
sortChildren_3()
$('#testytesty').sortChildren_3();
ready
sortChildren_4()
$('#testytesty').sortChildren_4();
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.