简体   繁体   中英

How to reverse the ordering of list items in an unordered list

Let's say I have an unordered list, like this:

<ul id="birds">
  <li>Bald Eagle</li>
  <li>Falcon</li>
  <li>Condor</li>
  <li>Albatross</li>
  <li>Parrot</li>
</ul>

With plain JavaScript (not including jQuery), I would like to be able to do reverse the order of this list - so that it matches the following expected "output":

<ul id="birds">
  <li>Parrot</li>
  <li>Albatross</li>
  <li>Condor</li>
  <li>Falcon</li>
  <li>Bald Eagle</li>
</ul>

This is the JavaScript I have attempted to code, to try and achieve this goal:

var birdList = document.getElementById("birds").getElementsByTagName("li");
var birdListReverse = birdList.reverse();

for(var i = 0; i < birdList.length; i++)
{
  birdList[i] = birdListReverse[i];
}

I would think that somehow over-writing the current list items with the ones in the "reversed" list would be sufficient, but not to be. Would I have to somehow manipulate each nodeValue in the list?

I would like to do this when a button is clicked - that is the easy part, it is just getting the technique to reverse the list that has hampered me a bit.

An HTMLCollection is only a read-only view of nodes. In order to manipulate nodes, you have to use one of the various DOM manipulation methods. In your case, there happens to be a shortcut; all you need do is to append the child nodes in reverse order.

var birds = document.getElementById("birds");
var i = birds.childNodes.length;
while (i--)
  birds.appendChild(birds.childNodes[i]);

Edit : What's happening is that appendChild removes the node from the document before appending it. This has two effects: a) it saves you from having to make a copy of the list of nodes and removing them before appending them in reverse order, and b) it reverses the order of nodes as it goes, since it appends the last child first and the first child list.

You can do it like this (in plain javascript). You can just cycle through the li tags in reverse order and append them to the parent. This will have the natural effect of reversing their order. You get the last one, append it to the end of the list, get the 2nd to last one, append it to the list. Get the 3rd to last one, append it to the end of the list and so on and all the items end up reversed. Note, you can use appendChild on something that is already in the DOM and it will be moved from it's current location automatically (eg removed before appended).

var birds = document.getElementById("birds");
var birdList = birds.getElementsByTagName("li");
for (var i = birdList.length - 1; i >= 0; i--) {
    birds.appendChild(birdList[i]);
}​

Working example: http://jsfiddle.net/jfriend00/GLvxV/

var birds = document.getElementById('birds');

for(var i = 0, bll = birds.childNodes.length; i < bll; i++) {
  birds.insertBefore(birds.childNodes[i], birds.firstChild);
}

 const list = document.querySelector("ul"); Array.from(list.children).reverse().forEach(element =>list.appendChild(element));

Manipulating the birdList doesn't re-order the elements because birdList is just a collection - a NodeList - which is independent of the DOM itself.

You actually need to get a reference to the <ul id="birds"> element and then use a combination of removeChild(...) and appendChild(...) - maybe insertBefore() .

Untested, but try:

var parent = document.getElementById("birds");
var birdList = parent.getElementsByTagName("li");

for(var i = birdList.length-1; i > 0; --i) {
    parent.appendChild(birdList[i];
}

There's actually no need for JavaScript. If you were to use the semantically correct <ol> (ordered list) element here (since ordering does obviously matter to you), then you can use the reversed attribute to do the exact same thing without any script-dependencies! To reverse the order of the items visually, we'd sprinkle in two lines of CSS with flex-direction :

 ol[reversed] { display: flex; flex-direction: column-reverse; }
 <ol reversed> <li>Bald Eagle</li> <li>Falcon</li> <li>Condor</li> <li>Albatross</li> <li>Parrot</li> </ol>

You can also do this. It works as follows:

  • Grab all the bird list items (the <li> elements) and return them as a NodeList
  • Convert the NodeList into an an array and reverse the array (since items in arrays can be reversed, but not items in NodeLists)
  • Append each bird list item from the array into the original list container (the <ul> element)

Code:

const birdsContainer = document.getElementById("birds");
const birdList = birds.getElementsByTagName("li");

[].slice.call(birdList)
  .reverse()
  .forEach(bird => birdsContainer.appendChild(bird));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM