Javascript - sorting a collection of divs

生来就可爱ヽ(ⅴ<●) 提交于 2021-02-04 18:07:30

问题


I am trying to learn Javascript alone so please don't suggest a library or jQuery.

I have a list of divs and I want the user to be able to sort them by their value. For example:

<button onclick="sort();">Test</button>
<div class="num">2</div>
<div class="num">3</div>
<div class="num">8</div>
<div class="num">1</div>

JS:

function sort(){
   var elements = document.getElementsByClassName("num");
   elements.sort();
}

I cannot find a straight answer to what's wrong with this. Does getElementsByClassName return an array of the values of each div with that name? How, when the array is then sorted, so I reflect the changes in the divs?


回答1:


You can't use the sort() function on a NodeList, which is what you are actually getting by calling getElementsByClassName

var elems = document.getElementsByClassName("num");

// convert nodelist to array
var array = [];
for (var i = elems.length >>> 0; i--;) { 
    array[i] = elems[i];
}

// perform sort
array.sort(function(a, b) {
    return Number(a.innerHTML) - Number(b.innerHTML);      
});

// join the array back into HTML
var output = "";
for (var i = 0; i < array.length; i++) { 
    output += array[i].outerHTML;
}

// append output to div 'myDiv'
document.getElementById('myDiv').innerHTML = output;

http://jsfiddle.net/UydrZ/7/

Of course, if you are using jQuery for this, it would be way easier. See jQuery - Sorting div contents




回答2:


Sorting nodes is not that simple, you may need to deal with other nodes that might get in the way. Anyhow, here's a function that accepts a NodeList or HTMLCollection, converts it to an array, sorts it, then puts the nodes back in order. Note that the elements are put back at the bottom of the parent element, so any other elements will end up at the top. Anyhow, it demonstrates an approach that you can adapt.

There are many other approaches, including others using DOM methods, beware of any that are based on munging the markup. Also, beware of cloning elements as this may have unwelcome side effects on listeners (they may or may not be removed, depending on the browser and how they've been added).

<script type="text/javascript">

function getText(el) {
  return el.textContent || el.innerText || '';
}

function sortElements(nodeList) {
  // Assume there's a common parent
  var node, parentNode = nodeList[0].parentNode

  // Define a sort function
  function sortEls(a, b) {
    var aText = getText(a);
    var bText = getText(b);
    return aText == bText? 0 : aText < bText? -1 : 1;
  }

  // Convert nodelist to an array and remove from the DOM at the same time
  var a = [], i = nodeList.length;
  while (i--) {
    a[i] = parentNode.removeChild(nodeList[i]);

  }

  // Sort the array
  a.sort(sortEls);

  // Put elements back in order
  i = 0;
  while (node = a[i++]) {
    parentNode.appendChild(node);
  }
}

</script>

<div>0</div>
<div>4</div>
<div>2</div>
<div>3</div>
<div>5</div>
<button onclick="sortElements(document.getElementsByTagName('div'))">Sort</button>



回答3:


The problem is that getElementsByClassName return a nodeList, not an array. Ok, I have to say, that is very stupid and I still can't get my head around why browser implemented it this way...

What you can do though, is first convert the nodeList to an array and than do the sorting:

var elems = Array.prototype.slice.call(elements);
elems.sort(/* function (a, b) {} */);

Note that the sorting function is optionnal and is passed normally after the first value. (Although, called directly on your elements list, .sort() won't sort anything without a function parameter as it won't know which one will come before the other)

Checkout MDN call description to understand how this really works behind the scene: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call



来源:https://stackoverflow.com/questions/16909451/javascript-sorting-a-collection-of-divs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!