I am trying to create a notification system that gives custom notifications. Here is my function:
var notificationCount = 0;
document.querySelector("body").innerHTML = '<div ></div>';
function notification(content){
notificationCount =1;
document.querySelector(".notification-holder").innerHTML = `
<div id="notification-${notificationCount}">
<p>${content}</p>
</div>
`;
var msg = document.querySelector(`#notification-${notificationCount}`);
msg.style.animation = "notificationAnimate 0.2s forwards"
msg.addEventListener("animationend", () => {
msg.style.visibility = "visible";
msg.style.animation = "";
setTimeout(() => {
msg.style.animation="notificationAnimate 0.2s reverse"
msg.addEventListener("animationend", () => {
msg.remove()
})
}, 1000)
})
};
:root{
--black: #151515;
--white: #EDEDEE;
}
.notification-holder{
position: absolute;
bottom: 0px;
right: 10px;
padding-bottom: 10px;
overflow: hidden;
}
.notification{
width: 250px;
padding: 10px;
text-align: center;
background-color: var(--black);
color: var(--white);
font-size: 14px;
font-family: "Poppins", sans-serif;
border-radius: 10px;
}
.notification:not(:first-of-type){
margin-top: 10px;
}
@keyframes notificationAnimate{
0%{
opacity: 0;
max-height: 1px;
transform: translateY(100px);
scale: 0;
}
100%{
opacity: 1;
max-height: fit-content;
transform: translateY(0px);
/* visibility: visible; */
scale: 1;
}
}
<html>
<head>
</head>
<body>
<button onclick="notification('Dark theme has been enabled!')">Dark theme </button>
</body>
</html>
The code works perfectly fine for 1 notification at a time. However, when there are multiple notifications at a time, only the latest one goes through the reverse
animation.
Regenerate Problem:
- Click on the button twice
- You will see only the latest notification goes back down. Earlier ones just stick there.
Expectation: I want all of them to go back down after 1s
of when they were shown.
CodePudding user response:
As noted in my earlier comment, I think the problem comes with you using notificationCount
in the ID/selector. That changes over time.
My solution removes the need for that, as well as all the document re-querying you were doing over time. Instead of tracking IDs and querying the DOM repeatedly, I create elements and store references to them, which I later act upon as needed.
My changes are in the JS, the rest of this snippet is from your post:
var notificationContainer,
notification;
notificationContainer = document.createElement('div');
notificationContainer.className = 'notification-holder';
document.body.appendChild(notificationContainer);
notification = function (content) {
var msg = document.createElement('div');
msg.className = 'notification';
msg.innerHTML = `<p>${content}</p>`;
msg.style.animation = 'notificationAnimate 0.2s forwards';
msg.addEventListener('animationend', function () {
msg.style.visibility = 'visible';
msg.style.animation = '';
setTimeout(function () {
msg.style.animation='notificationAnimate 0.2s reverse';
msg.addEventListener('animationend', function () {
msg.remove();
});
}, 1000);
});
notificationContainer.appendChild(msg);
};
:root{
--black: #151515;
--white: #EDEDEE;
}
.notification-holder{
position: absolute;
bottom: 0px;
right: 10px;
padding-bottom: 10px;
overflow: hidden;
}
.notification{
width: 250px;
padding: 10px;
text-align: center;
background-color: var(--black);
color: var(--white);
font-size: 14px;
font-family: "Poppins", sans-serif;
border-radius: 10px;
}
.notification:not(:first-of-type){
margin-top: 10px;
}
@keyframes notificationAnimate{
0%{
opacity: 0;
max-height: 1px;
transform: translateY(100px);
scale: 0;
}
100%{
opacity: 1;
max-height: fit-content;
transform: translateY(0px);
/* visibility: visible; */
scale: 1;
}
}
<html>
<head>
</head>
<body>
<button onclick="notification('Dark theme has been enabled!')">Dark theme </button>
</body>
</html>
CodePudding user response:
Here you go, may require some fine tuning, but works as expected:
document.querySelector("body").innerHTML = '<div ></div>';
function notification(content){
var msg = document.createElement('div');
msg.innerHTML = `
<div >
<p>${content}</p>
</div>
`
document.querySelector(".notification-holder").appendChild(msg);
msg.style.animation = "notificationAnimate 0.2s forwards"
msg.addEventListener("animationend", () => {
msg.style.visibility = "visible";
msg.style.animation = "";
setTimeout(() => {
msg.style.animation="notificationAnimate 0.2s reverse"
msg.addEventListener("animationend", () => {
msg.remove()
})
}, 1000)
})
};
:root{
--black: #151515;
--white: #EDEDEE;
}
.notification-holder{
position: absolute;
bottom: 0px;
right: 10px;
padding-bottom: 10px;
overflow: hidden;
}
.notification{
width: 250px;
padding: 10px;
text-align: center;
background-color: var(--black);
color: var(--white);
font-size: 14px;
font-family: "Poppins", sans-serif;
border-radius: 10px;
}
.notification:not(:first-of-type){
margin-top: 10px;
}
@keyframes notificationAnimate{
0%{
opacity: 0;
max-height: 1px;
transform: translateY(100px);
scale: 0;
}
100%{
opacity: 1;
max-height: fit-content;
transform: translateY(0px);
/* visibility: visible; */
scale: 1;
}
}
<html>
<head>
</head>
<body>
<button onclick="notification('Dark theme has been enabled!')">Dark theme </button>
</body>
</html>
BTW, nice script :-)