jQuery Sorting Children (30)

JavaScript performance comparison

Test case created by Rodney

Preparation code

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.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>
</ul>
      
<script>
Benchmark.prototype.setup = function() {
  // 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));
          });
   
      };
   
  })();

};

Benchmark.prototype.teardown = function() {
  $('#testytesty').remove();

};
</script>

Preparation code output

<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> </ul>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
sortElements()
$('#testytesty').children().sortElements(function(a, b){
    return $(a).text().toLowerCase() > $(b).text().toLowerCase() ? 1 : -1;
});
pending…
sortChildren_1()
$('#testytesty').sortChildren_1();
pending…
sortChildren_2()
$('#testytesty').sortChildren_2();
pending…
sortChildren_3()
$('#testytesty').sortChildren_3();
pending…
sortChildren_4()
$('#testytesty').sortChildren_4();
pending…

Compare results of other browsers

Revisions

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

0 Comments