Lovelock
Lovelock

Reputation: 8075

Repeating loop through list elements that adds a class to each with javascript

I have a UL containing list elements. I need to create an effect that highlights each list item in order and changes their background colour.

This is just a highlight affect that will add / remove a class every second and move along the list.

Basic html:

<ul id="looping-list">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    etc...
</ul>

I am currently stuck at this:

var ul = document.getElementById("looping-list");
var items = ul.getElementsByTagName("li");
for (var i = 0; i < items.length; i++) {

}

Thanks. If required I can alter the html of the list to give an id to each of the elements or a data attribute as they are coming from a PHP for loop.

No jQuery on this one too.

Upvotes: 0

Views: 80

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1073988

You can't do it with for because you need to yield back to the browser for that second between changes. But other than that, you're on the right sort of track.

Here's an example using setTimeout. I've assumed you want to keep looping through them, going back to the beginning when you reach the end. This version also happily adjusts to changes in the list, if you add/remove items dynamically.

// Strict mode helps us avoid errors like The Horror of Implicit Globals
"use strict";

// A scoping function to avoid creating global variables
(function() {
  // An index we'll use to keep track of which element should be next.
  // We'll pre-increment it, so start with -1.
  var index = -1;

  // Start the process
  update();
  
  function update() {
    // Get the list
    var list = document.getElementById("looping-list");
    
    // Remove the old highlight, if any
    var item = list.querySelector("li.highlighted");
    if (item) {
      // There is, remove it
      item.classList.remove("highlighted");
    }
    
    // Move to the next, wrapping around if appropriate
    var items = list.querySelectorAll("li");
    index = (index + 1) % items.length;
    
    // Add the class
    items[index].classList.add("highlighted");
    
    // Schedule a callback after a second
    // Add an `if` here if there's a termination condition
    setTimeout(update, 1000);
  }
})();
.highlighted {
  color: blue;
}
<ul id="looping-list">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
</ul>


Note: This uses classList, which in the simple usage above is very well-supported in modern browsers and can be shimmed on older browsers (IE9 and earlier) if needed.

Upvotes: 1

Luke P
Luke P

Reputation: 734

If I understand you correctly, something like this:

var ul = document.getElementById("looping-list");
var items = ul.getElementsByTagName("li");
for (var i = 0; i < items.length; i++) {
  doSetTimeout(items[i], i);
}


function doSetTimeout(elm, i) {
  setTimeout(function() {
  	elm.style.backgroundColor = 'red';
  }, 200*i);
}
<ul id="looping-list">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
</ul>

Upvotes: 0

Related Questions