jQuery Sorting Children (30) (v2)

Revision 2 of this benchmark created on


Preparation HTML

<script src="//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>

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.