Skyyy
Skyyy

Reputation: 1569

onclick not responding properly when adding/removing very fast

I am kind of trying to make a slot machine. To create slot machine affect i'am removing first div from the wrapper and adding it back to the bottom. onClick events works fine when i am using a value of 1000ms but when i use something like 100ms interval then i need to click multiple times rapidly for it to register click events. Why this behavior?

Also on touch screen (Checked on my mobile) i don't encounter this issue.

setInterval(function() {

  swap_box();
}, 100);

function swap_box() {
  let first_box = document.getElementsByClassName("box")[0];
  first_box.remove();
  document.getElementsByClassName("div-wrapper")[0].appendChild(first_box);

  first_box.addEventListener("click", function() {
    console.log(this.innerText);
  });

}
.box {
  width: 100px;
  height: 50px;
  border: 1px solid black;
}
<div class="div-wrapper">
  <div class="box">0</div>
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
  <div class="box">7</div>
</div>

Upvotes: 3

Views: 538

Answers (1)

Jacob
Jacob

Reputation: 78848

I have three recommendations:

  1. Instead of attaching a click handler within the setInterval handler, only set click handlers once. Removing an element does not remove its event handlers, so you're getting duplicate handlers attached in a loop.
  2. Instead of attaching the handlers to each item, you can "virtualize" it by having the parent handle the event for all children.
  3. The reason why click isn't working very well with elements moving around so much is that a click is made up of a mouse down and mouse up, so if the element moves out from under your pointer between these phases, it may not work. One solution is to use the mousedown event instead.

let container = document.querySelector('.div-wrapper');

function handleClick(e) {
  if (e.target.className === 'box') {
    console.log(first_box.innerText);
  }
}

container.addEventListener("mousedown", handleClick, false);

setInterval(swap_box, 100);

function swap_box() {
  const first_box = document.getElementsByClassName("box")[0];
  first_box.remove();
  container.appendChild(first_box);
}
.box {
  width: 100px;
  height: 50px;
  border: 1px solid black;
}
<div class="div-wrapper">
  <div class="box">0</div>
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
  <div class="box">7</div>
</div>

Upvotes: 4

Related Questions