Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Array.prototype.sort.call to sort a HTMLCollection

var down=function(a,b){alert(a)}
Array.prototype.sort.call(table.tBodies[0].childNodes,down)
Array.prototype.sort.call([0,1,2,3],down)

Why do I not get alerts from the first sort call?

like image 745
Gert Cuykens Avatar asked Nov 30 '22 07:11

Gert Cuykens


2 Answers

Convert the NodeList to an array first:

var elements = [].slice.call(table.tBodies[0].childNodes);

and then call sort normally:

elements.sort(down);

It seems sort cannot handle array-like objects. This is probably because NodeList does not provide any methods to change the list, but sort sorts the array in-place.

Update: For more information, from the specification:

Perform an implementation-dependent sequence of calls to the [[Get]] , [[Put]], and [[Delete]] internal methods of obj.

I assume NodeLists don't have these internal methods. But this is really just an assumption. It could also be that this is implementation dependent.

I also suggest you use .children [MDN] instead of .childNodes to only get element nodes. Update: Or .rows [DOM Spec] as @patrick suggests.

like image 94
Felix Kling Avatar answered Dec 05 '22 12:12

Felix Kling


My proposal to sort an HTMLCollection is:

window.onload = function() {
  var parentNode = document.getElementById('test-list');
  var e = document.getElementById('test-list').children;
  [].slice.call(e).sort(function(a, b) {
    return a.textContent.localeCompare(b.textContent);
  }).forEach(function(val, index) {
    parentNode.appendChild(val);
  });
}
<ol id="test-list">
    <li class="lang">Scheme</li>
    <li class="lang">JavaScript</li>
    <li class="lang">Python</li>
    <li class="lang">Ruby</li>
    <li class="lang">Haskell</li>
</ol>
like image 23
gaetanoM Avatar answered Dec 05 '22 12:12

gaetanoM