1

I m making a Toast Notification.

I hope that When I click the 'Toast Notification' button, notification message come to on the bottom side and after a while, the messages disappear.

So I set the disappearing time to 5s , then after clicking the button and later 5 second , the messages are disappeared in sequence.

But the disappearing time was not the 5second except the first disappearing .

Time is getting faster and faster that is disappeared . It's not 5 second what I set before

My english is bad so I hope you understand by running code below

let toast = document.querySelector('.toast');
let notification = document.querySelector(".notification")
let sec = 5000;

toast.addEventListener('click', () => {
  let newDiv = document.createElement("span");
  let newText = document.createTextNode("No Way!");
  newDiv.classList.add("notification_word");
  newDiv.appendChild(newText);
  notification.appendChild(newDiv);

  if (document.querySelector(".notification_word")) {
    setInterval(function() {
      removeNotification()
    }, sec);
  }

})

function removeNotification() {
  document.querySelectorAll(".notification_word")[0].remove()
}
body {
  text-align: center;
  justify-content: center;
  align-items: center;
}

button.toast {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 200px;
  height: 100px;
  font-size: 20px;
  background: rgb(215, 188, 240);
  margin: -100px 0 0 -100px;
  border: 1px solid rgb(28, 3, 51);
  border-radius: 20px;
  cursor: pointer;
}

button.toast:hover {
  background: rgb(178, 157, 201);
}

.notification {
  display: flex;
  flex-direction: column-reverse;
  position: absolute;
  right: 2%;
  bottom: 2%;
}

span.notification_word {
  background-color: rgb(196, 77, 243);
  padding: 10px 0;
  margin: 3px;
  width: 100px;
  border: 1px solid rgb(28, 3, 51);
  border-radius: 5px;
}
<button class="toast">Toast Notification</button>
<div class="notification">
</div>
Satpal
  • 132,252
  • 13
  • 159
  • 168
FishKing
  • 59
  • 4
  • 1
    As per you need, use `setTimeout` instead of `setInterval`. The problem with your implementation is that you are not cancelling the timed, repeating action which was previously established by a call to `setInterval()` – Satpal Jun 11 '21 at 05:52

5 Answers5

1

Try this code I have written some comment on code it may help you

let toast = document.querySelector('.toast');
let notification = document.querySelector(".notification")
let sec = 5000;
let timeoutHandler;

toast.addEventListener('click', () => {
  // clear previous timeout function
  clearTimeout(timeoutHandler);
  //remove previous notification if exist
  //if you don't want to remove previous notification than remove below calling function.
  removeNotification();

  let newDiv = document.createElement("span");
  let newText = document.createTextNode("No Way!");
  newDiv.classList.add("notification_word");
  newDiv.appendChild(newText);
  notification.appendChild(newDiv);

  if (document.querySelector(".notification_word")) {
  // use timeout function instead of setinterval and assign on a variable
    timeoutHandler = setTimeout(function() {
      removeNotification()
    }, sec);
  }

})

function removeNotification() {
  let notificationWord = document.querySelector(".notification_word");
  if(notificationWord) notificationWord.remove();
}
body {
  text-align: center;
  justify-content: center;
  align-items: center;
}

button.toast {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 200px;
  height: 100px;
  font-size: 20px;
  background: rgb(215, 188, 240);
  margin: -100px 0 0 -100px;
  border: 1px solid rgb(28, 3, 51);
  border-radius: 20px;
  cursor: pointer;
}

button.toast:hover {
  background: rgb(178, 157, 201);
}

.notification {
  display: flex;
  flex-direction: column-reverse;
  position: absolute;
  right: 2%;
  bottom: 2%;
}

span.notification_word {
  background-color: rgb(196, 77, 243);
  padding: 10px 0;
  margin: 3px;
  width: 100px;
  border: 1px solid rgb(28, 3, 51);
  border-radius: 5px;
}
<button class="toast">Toast Notification</button>
<div class="notification">
</div>
Sparrow
  • 280
  • 1
  • 12
1

Happens in your code -> 5 seconds after you click the button, the notification that appears after you click the button disappears.

In the code I wrote, after a delay of 5 seconds it will remove the oldest notification: it will loop

I think you can understand.

Try this code ...

  let toast = document.querySelector('.toast');
  let notification = document.querySelector(".notification");
  let sec = 5000;
  let Divarray = [];
  let arraynum = 0;

  toast.addEventListener('click', () => {
    let newDiv = document.createElement("span");
    let newText = document.createTextNode("No Way!"+arraynum);
    newDiv.classList.add("notification_word");
    newDiv.appendChild(newText);
    notification.appendChild(newDiv);
    Divarray[arraynum] = newDiv;
    arraynum += 1;
  })
  function array(){
    setInterval(function(){
      Divarray.splice(arraynum, 1);
      removeNotification();
      
    },sec);
  }
  array();

  function removeNotification() {
    document.querySelectorAll(".notification_word")[0].remove();
  }
body {
  text-align: center;
  justify-content: center;
  align-items: center;
}

button.toast {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 200px;
  height: 100px;
  font-size: 20px;
  background: rgb(215, 188, 240);
  margin: -100px 0 0 -100px;
  border: 1px solid rgb(28, 3, 51);
  border-radius: 20px;
  cursor: pointer;
}

button.toast:hover {
  background: rgb(178, 157, 201);
}

.notification {
  display: flex;
  flex-direction: column-reverse;
  position: absolute;
  right: 2%;
  bottom: 2%;
}

span.notification_word {
  background-color: rgb(196, 77, 243);
  padding: 10px 0;
  margin: 3px;
  width: 100px;
  border: 1px solid rgb(28, 3, 51);
  border-radius: 5px;
}
<button class="toast">Toast Notification</button>

<div class="notification">
</div>
0

Replacing setInterval with setTimeout should fix your problem.

setTimeout(() => { removeNotification(); }, sec);

you can learn more from here: setTimeout or setInterval?

ahsan
  • 1,409
  • 8
  • 11
0

setInterval would execute every specified interval unless its cleared using clearInterval. You could check if there exists any other .notification_word classes, if not clearInterval. Or a simple no brainer would be to replace setInterval with setTimeout. The latter will execute only once after 5 secs, which seems the ideal solution to what you seem to achieve.

0

At first, when you use the queryselectorAll javascript delete every single toast that match with the classname. I assume that is not the intention of a toast notification. So i created a new piece of code that handle removing the specific element. second, the javascript interval fires every preset seconds, but your intention is one time! so instead of using interval i recommend to use the setTimeout function.

To avoid double ids i created an object where ids are being 'parked'.

let toast = document.querySelector('.toast');
let notification = document.querySelector(".notification")
let sec = 5000;
let UID = {};

toast.addEventListener('click', () => {
  let newDiv = document.createElement("span");
  let newText = document.createTextNode("No Way!");
  
  let id = Math.floor(Math.random() * 100);
  let check = false
  
  while(check == false) {
  
    if(id in UID == false) {
      UID[ id ] = {};
      check = true;
    } else {
       id = Math.floor(Math.random() * 100);
    }
    
  }  
  
  newDiv.id = id;
  
  newDiv.classList.add("notification_word");
  newDiv.appendChild(newText);
  notification.appendChild(newDiv);

if (document.getElementById(id)) {
    setTimeout(function() {
      document.getElementById(id).remove()
      delete UID[ id ];
    }, sec);
  }
})
body {
  text-align: center;
  justify-content: center;
  align-items: center;
}

button.toast {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 200px;
  height: 100px;
  font-size: 20px;
  background: rgb(215, 188, 240);
  margin: -100px 0 0 -100px;
  border: 1px solid rgb(28, 3, 51);
  border-radius: 20px;
  cursor: pointer;
}

button.toast:hover {
  background: rgb(178, 157, 201);
}

.notification {
  display: flex;
  flex-direction: column-reverse;
  position: absolute;
  right: 2%;
  bottom: 2%;
}

span.notification_word {
  background-color: rgb(196, 77, 243);
  padding: 10px 0;
  margin: 3px;
  width: 100px;
  border: 1px solid rgb(28, 3, 51);
  border-radius: 5px;
}
<body>
  <button class="toast">Toast Notification</button>

  <div class="notification">

  </div>
Henri Bunt
  • 69
  • 1
  • 3