Rob
Rob

Reputation: 1280

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.

Upvotes: 5

Views: 11726

Answers (8)

kano
kano

Reputation: 5926

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>

Upvotes: 0

CodeBiker
CodeBiker

Reputation: 3263

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));

Upvotes: 0

a.keramati
a.keramati

Reputation: 11

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

Upvotes: 1

Oleg Vaskevich
Oleg Vaskevich

Reputation: 12672

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];
}

Upvotes: 0

jfriend00
jfriend00

Reputation: 707716

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 (e.g. 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/

Upvotes: 1

Neil
Neil

Reputation: 55402

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.

Upvotes: 17

Brett Zamir
Brett Zamir

Reputation: 14355

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

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

Upvotes: 1

Richard JP Le Guen
Richard JP Le Guen

Reputation: 28753

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().

Upvotes: 0

Related Questions