Home > Net >  clearTimeout() doesn't work when called from an event
clearTimeout() doesn't work when called from an event

Time:01-28

This is a summarized example of another larger project I have. In this example I set a new style for my node when I click on it, once the new style is set I fire a setTimeout() to allow the style for a few seconds until it desappear. on the other hand, I have a keydown event that is supposed to cancel the Timeout when I press any key. So if the timeout is canceled with clearTimeout(), the box is supposed to stay styled, but it is not working. The clearTimeout() doesn't cancel the timeout, and doesn't prevent the style to be deleted.

Any idea about what is wrong with the clearTimeout()?

const box = document.querySelector("div")

let timeout

box.onclick = () =>{
    box.classList.add("black")
}

box.ontransitionend = () =>{
    timeout = setTimeout(() =>{
        box.classList.remove("black")
    }, 3000)
}

window.onkeydown = () =>{
    clearTimeout(timeout)
}
*{
    margin: 0px;
    padding: 0px;
}

.box{
    width: 200px;
    height: 200px;
    margin: auto;
    border: #333 1px solid;

    transition: all 1s ease-in-out 0s;
}

.black{
    background-color: black;
    border: #ccc 1px solid;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>test</title>
    <link rel="stylesheet" href="./styles.css">
</head>
<body>
    
    <div >

    </div>

    <script src="./main.js"></script>
</body>
</html>

CodePudding user response:

I've noticed that the event ontransitionend fires once for each style in the class i've set, so i'm creating more than one Timeout.

CodePudding user response:

The ontransitionend event gets called for each transitioned style, in your case, that's your background-color, as well as border-top-color, border-right-color, border-bottom-color and border-left-color for the border style change due to the all in your transitional: all ... style. You could apply a check in your event handler to only apply your timeout when the transition is for CSS style background-color by using event.propertyName. This way you won't end up creating multiple timeouts and will be able to cancel it.:

const box = document.querySelector("div");

let timeout;

box.onclick = () => {
  box.classList.add("black")
}

box.ontransitionend = (event) => {
  if (event.propertyName === "background-color") {
    timeout = setTimeout(() => {
      box.classList.remove("black")
    }, 3000);
  }
}

window.onkeydown = () => {
  clearTimeout(timeout);
}
* {
  margin: 0px;
  padding: 0px;
}

.box {
  width: 200px;
  height: 200px;
  margin: auto;
  border: #333 1px solid;
  transition: all 1s ease-in-out 0s;
}

.black {
  background-color: black;
  border: #ccc 1px solid;
}
<div ></div>

  • Related