h0bb5 h0bb5 - 3 years ago 156
HTML Question

How to add class to random element in pure javascript

I have a ul with some

li
's inside.
I want to randomly select an
li
and add an
.active
class for 1second, then remove
.active
class and randomly select a next
li
.

I am trying to do this without the use of setInterval or Timeout, so I have tried using requestAnimationFrame although I think my logic with javascript is not quite right on randomizing.

Currently I have it working but it selects the same
li
each time the function is called again.

<ul>
<li class="light active"></li>
<li class="light"></li>
<li class="light"></li>
<li class="light"></li>
<li class="light"></li>
</ul>


Javascript

(function() {

var lights = document.getElementsByClassName("light");
var random = Math.floor(Math.random() * (lights.length - 1)) + 0;
var randomLight = lights[random];

function repeatOften() {
randomLight.classList += randomLight.classList ? ' active' : ' light';
requestAnimationFrame(repeatOften);
}
requestAnimationFrame(repeatOften);

})();


Here is a pen: https://codepen.io/H0BB5/pen/PJjapX?editors=0010

Thanks in advance!

Answer Source

The right choice to run a function in a more-or-less known time in the future is setTimeout. requestAnimationFrame is meant for something that should run as often as is feasible without interrupting the render loop, say 60 times a second (aka "at 60 fps").

In your case you have a relatively slow update rate of once a second, so setTimeout isn't hurting.

You probably want to keep track of two elements: The one you're changing and the one you previously changed, so you can reset it.

Also, classList.toggle comes in handy as it adds or removes a class, based on if it's already present or not.

(function() {
  var lights = document.getElementsByClassName("light");
  var previousLight = null;

  function repeatOften() {
    if (previousLight) previousLight.classList.toggle('active')

    var random = Math.floor(Math.random() * (lights.length - 1)) + 0;
    var randomLight = lights[random];
    randomLight.classList.toggle(randomLight);
    previousLight = randomLight;
    setTimeout(repeatOften, 1000);
  }

  setTimeout(repeatOften, 1000);
})();

Here is the updated (and slightly changed) pen.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download