Don't Override setTimeout - javascript

I am trying to create a notification system that gives custom notifications. Here is my function:
var notificationCount = 0;
document.querySelector("body").innerHTML += '<div class="notification-holder"></div>';
function notification(content){
notificationCount+=1;
document.querySelector(".notification-holder").innerHTML += `
<div class="notification" 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.

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>

Here you go, may require some fine tuning, but works as expected:
document.querySelector("body").innerHTML += '<div class="notification-holder"></div>';
function notification(content){
var msg = document.createElement('div');
msg.innerHTML += `
<div class="notification">
<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 :-)

Related

How to create a square box in which the border of the box will be filled by color depending on the value given on the box?

Just like the above image or an idea or reference to achieve this design, I appreciate the help or suggestion given by community thank you
I have got reference of progress bar which is circular but not able find an approach to solve it.
const boxes = document.querySelectorAll(".box");
const colors = ['red', 'blue', 'green', 'yellow', 'orange', 'violet']
boxes.forEach((box) => {
const insideContent = box.innerText;
box.style.border = `6px solid ${colors[insideContent]}`
})
#app {
display: flex;
}
.box {
width: 50px;
height: 50px;
margin: 10px;
background-color: cyan;
display: flex;
justify-content: center;
align-items: center;
}
<div id="app">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
</div>
As per your question I think this is what you are trying to achieve.
First define a pseudo class root
:root {
--color-val: blue;
}
Note: In order to use the --color-val you need to write it as color: var(--color-var) in CSS
Second use JavaScript to update the variable --color-val
let colors =
var root = document.querySelector(':root');
const delay = ms => new Promise(res => setTimeout(res, ms));
const colorChange = async () => {
await delay(1000);
color = colors[Math.floor(Math.random() * colors.length)]
console.log(color)
root.style.setProperty('--color-val', color);
};
colorChange()
Note:
Add the color list you want to select from or go to CodePen for a list of 1000+ hex codes.
Promise are used for asynchronous function and can be skipped by using setTimeOut for a delayed loop or if used with another eventlistener.
I apologize if I misunderstood the question. Wrote in a hurry and without beautyful visualisation, if you disassemble the principle, you can customize it.
h1 {
display: block;
margin:0 auto;
text-align: center;
padding-top:20%;
}
.container {
display:flex;
width: 150px;
height: 150px;
border: 1px solid black;
z-index: 110;
margin:0;
margin: -10px;
}
.top {
display:block;
background-color: green;
height: 24px;
width: 150px; /* gorizontal top */
animation: top 1s linear;
animation-fill-mode: forwards;
}
#keyframes top {
0% {
width: 0px;
}
100% {
width: 150px;
}
}
.right {
background-color: green;
height: 0%;/* right */
width: 32px;
animation: right 1s linear;
animation-fill-mode: forwards;
animation-delay: 1s;
z-index: 10;
}
#keyframes right {
0% {
height: 0%;
}
100% {
height: 100%;
}
}
.box {
position: fixed;
top: 32.5px;
left: 32.5px;
width: 100px;
height: 100px;
border: 1px solid black;
margin: auto;
z-index: 120;
margin: -10px -10px;
}
.bottom {
position: absolute;
top: 123px;
left: 150px;
background-color: green;
width: 0px;
height: 27px;
z-index: 10;
animation: bottom 1s linear;
animation-fill-mode: forwards;
animation-delay: 2s;
/* animation-direction: reverse; */
}
#keyframes bottom {
0% {
transform: translate(0,0);
}
100% {
transform: translate(-250px,0);
-webkit-transform: translate(-250px,0); /** Safari & Chrome **/
-o-transform: translate(-250px,0); /** Opera **/
-moz-transform: translate(-250px,0); /** Firefox **/
width: 250px;
}
}
.left {
position: absolute;
top: 122px;
background-color: green;
width: 25px;
height: 0px;
animation: left 1s linear;
animation-fill-mode: forwards;
animation-delay: 3s;
}
#keyframes left {
0% {
transform: translate(0,0);
}
100% {
transform: translate(0,-250px);
-webkit-transform: translate(0,-250px); /** Safari & Chrome **/
-o-transform: translate(0,-250px); /** Opera **/
-moz-transform: translate(0,-250px); /** Firefox **/
height: 277px;
}
}
<div class='head'>
<div class='container'>
<div class='top'></div>
<div class='box'>
<h1 id='timer'>
1
</h1>
</div>
<div class='right'></div>
<div class='bottom'></div>
<div class='left'></div>
</div>
</div>
<script type="text/javascript">
init()
function init()
{
sec = 0;
setInterval(tick, 1000);
}
function tick()
{ if (sec<3) { sec++
document.getElementById("timer").
childNodes[0].nodeValue = sec;
} else {
clearInterval(0);
}
}
</script>
Also, instead of the SetInterval script, you can take values from your block width and height styles and output a mathematical calculation in h1 instead of a stopwatch.
upd: After your comment, I decided to do what I wrote about above. You can play with values and math, I add a snippet of another solution that changes the progress bar from the entered values within the entered range. (of course, it would be easier on react than on pure js)
function grade () {
let grade = +document.getElementById("grade").value;
let range = +document.getElementById("range").value;
document.getElementById("timer").innerHTML = `${grade}/${range}`;
progress(grade,range)
}
function progress (value, grade) {
document.getElementById('1').style.backgroundColor = `white`
document.getElementById("left").className = "noactive";
document.getElementById('top').style.width = `0%`
document.getElementById('right').style.height = `0%`
document.getElementById('bottom').style.width = `0%`
let GradeValuSide = grade/4;
if (value <= GradeValuSide) {
document.getElementById('top').style.width =
`${value/GradeValuSide*100}%`
} else if (value > GradeValuSide && value <= (GradeValuSide*2)) {
document.getElementById('top').style.width = `100%`
document.getElementById('right').style.height =
`${(value-GradeValuSide)/GradeValuSide*100}%`
} else if (value >= grade/2 && value < (grade/4)*3) {
document.getElementById('top').style.width = `100%`
document.getElementById('right').style.height = `100%`
document.getElementById('bottom').style.width =
`${((((value-(GradeValuSide*2)) / GradeValuSide) *100) / 100) *27}%`
} else if (value >= grade-(grade/4) /* && value < value + 1 */) {
document.getElementById('top').style.width = `100%`
document.getElementById('right').style.height = `100%`
document.getElementById('bottom').style.width = `100%`
document.getElementById('1').style.backgroundColor = `green`
document.getElementById("left").className = "left";
document.getElementById('left').style.height =
`${(40 - (40 * ((((value-(GradeValuSide*3)) * 100) / GradeValuSide)/ 100)))}%`
}
}
h1 {
font-size:20px;
position: absolute;
left: 40px;
display: block;
margin: 0 auto;
align-items: center;
padding-top:10%;
}
.container {
display:flex;
width: 150px;
height: 150px;
border: 1px solid black;
margin:0;
margin: -10px;
}
div.top {
display:block;
background-color: green;
height: 24px;
width: 0%; /* gorizontal top */
z-index:999;
}
div.right {
position:relative;
background-color: green;
height: 0%;/* right */
width: 32px;
z-index: 9999;
}
.box {
position: fixed;
top: 32.5px;
left: 32.5px;
background-color:white;
width: 100px;
height: 100px;
border: 1px solid black;
margin: auto;
z-index: 120;
margin: -10px -10px;
}
.wrap{
position: relative;
}
div.bottom {
position: absolute;
top: 123px;
background-color: green;
width: 0%; /* 27 = 100% */
height: 27px;
float: right;
right: 78vw;
z-index: 100;
}
div.left {
position: absolute;
background-color: white;
width: 23px;
height: 40%;
top: 23px;
bottom: 10px;
left: 0;
float: top;
}
div.noactive {
position: absolute;
background-color: white;
width: 23px;
height: 0%;
top: 23px;
bottom: 10px;
left: 0;
float: top;
}
.items {
margin-top: 50px;
text-align: center;
}
.grade,
.value {
height: 15px;
width: 50px;
align-items: center;
}
<div class='head'>
<div id='1' class='container'>
<div id='top' class='top'></div>
<div class='box'>
<h1 id='timer'>1</h1>
<div class='items'>
value<input id='grade' class='grade' type=number oninput="grade()"/>
range<input id='range' class='value' type=number oninput="grade()"/>
</div>
</div>
<div id='right' class='right'></div>
<div id='bottom' class='bottom'></div>
<div id='left' class='noactive'></div>
</div>
</div>
<script src='app.js'></script>

How to integrate AWS IVS with JW Player?

I'm trying to follow this IVS sample, the only difference is using the JW player, I following this documentation
The problem is that this snippet
jwplayer(videoPlayer).addEventListener(
PlayerEventType.TEXT_METADATA_CUE,
function (cue) {
const metadataText = cue.text;
const position = player.getPosition().toFixed(2);
console.log(
`Player Event - TEXT_METADATA_CUE: "${metadataText}". Observed ${position}s after playback started.`
);
triggerQuiz(metadataText);
}
);
is giving this error
script.js:60 Uncaught TypeError: Cannot read properties of undefined (reading 'TEXT_METADATA_CUE')
I'm either not adding an event listener to the jw player correctly or I'm doing something wrong while working with IVS.
My full code is below
const playbackUrl =
"https://fcc3ddae59ed.us-west-2.playback.live-video.net/api/video/v1/us-west-2.893648527354.channel.xhP3ExfcX8ON.m3u8";
const videoPlayer = document.getElementById("video-player");
const quizEl = document.getElementById("quiz");
const waitMessage = document.getElementById("waiting");
const questionEl = document.getElementById("question");
const answersEl = document.getElementById("answers");
const cardInnerEl = document.getElementById("card-inner");
var ivsPlayer = {};
var ivsEvents = {};
const ivsConfig = {
playlist: [
{
file: playbackUrl,
type: "ivs",
},
],
};
(function (ivsPlayer) {
jwplayer(videoPlayer)
.setup(ivsConfig)
.on("providerPlayer", function (player) {
console.log("Amazon IVS Player: ", player.ivsPlayer);
console.log("Amazon IVS Player Events: ", player.ivsEvents);
// store the reference to the Amazon IVS Player
ivsPlayer = player.ivsPlayer;
// store the reference to the Amazon IVS Player Events
ivsEvents = player.ivsEvents;
});
const PlayerState = ivsPlayer.PlayerState;
const PlayerEventType = ivsPlayer.PlayerEventType;
jwplayer(videoPlayer).addEventListener(
PlayerEventType.TEXT_METADATA_CUE,
function (cue) {
const metadataText = cue.text;
const position = player.getPosition().toFixed(2);
console.log(
`Player Event - TEXT_METADATA_CUE: "${metadataText}". Observed ${position}s after playback started.`
);
triggerQuiz(metadataText);
}
);
// Setup stream and play
// Remove card
function removeCard() {
quizEl.classList.toggle("drop");
}
// Trigger quiz
function triggerQuiz(metadataText) {
let obj = JSON.parse(metadataText);
quizEl.style.display = "";
quizEl.classList.remove("drop");
waitMessage.style.display = "none";
cardInnerEl.style.display = "none";
cardInnerEl.style.pointerEvents = "auto";
while (answersEl.firstChild) answersEl.removeChild(answersEl.firstChild);
questionEl.textContent = obj.question;
let createAnswers = function (obj, i) {
let q = document.createElement("a");
let qText = document.createTextNode(obj.answers[i]);
answersEl.appendChild(q);
q.classList.add("answer");
q.appendChild(qText);
q.addEventListener("click", (event) => {
cardInnerEl.style.pointerEvents = "none";
if (q.textContent === obj.answers[obj.correctIndex]) {
q.classList.toggle("correct");
} else {
q.classList.toggle("wrong");
}
setTimeout(function () {
removeCard();
waitMessage.style.display = "";
}, 1050);
return false;
});
};
for (var i = 0; i < obj.answers.length; i++) {
createAnswers(obj, i);
}
cardInnerEl.style.display = "";
}
waitMessage.style.display = "";
})(window.ivsPlayer);
Edit see the snippet
const playbackUrl =
"https://fcc3ddae59ed.us-west-2.playback.live-video.net/api/video/v1/us-west-2.893648527354.channel.xhP3ExfcX8ON.m3u8";
const ivsConfig = {
playlist: [
{
file: playbackUrl,
type: "ivs",
},
],
};
const videoPlayer = document.getElementById("video-player");
const quizEl = document.getElementById("quiz");
const waitMessage = document.getElementById("waiting");
const questionEl = document.getElementById("question");
const answersEl = document.getElementById("answers");
const cardInnerEl = document.getElementById("card-inner");
(async (IVSPlayer) => {
try {
const playerInstance = jwplayer(videoPlayer).setup(ivsConfig);
playerInstance.on("providerPlayer", function (player) {
console.log("Amazon IVS Player: ", player.ivsPlayer);
console.log("Amazon IVS Player Events: ", player.ivsEvents);
const PlayerEventType = player.ivsEvents;
playerInstance.addEventListener(
PlayerEventType.TEXT_METADATA_CUE,
function (cue) {
const metadataText = cue.text;
const position = player.getPosition().toFixed(2);
console.log(metadataText);
//console.log(
// `Player Event - TEXT_METADATA_CUE: "${metadataText}". Observed ${position}s after playback started.`
//);
//onsole.log(cue);
//triggerQuiz(metadataText);
}
);
});
} catch (e) {
console.error(e);
}
function triggerQuiz(metadataText) {
let obj = JSON.parse(metadataText);
quizEl.style.display = "";
quizEl.classList.remove("drop");
waitMessage.style.display = "none";
cardInnerEl.style.display = "none";
cardInnerEl.style.pointerEvents = "auto";
while (answersEl.firstChild) answersEl.removeChild(answersEl.firstChild);
questionEl.textContent = obj.question;
let createAnswers = function (obj, i) {
let q = document.createElement("a");
let qText = document.createTextNode(obj.answers[i]);
answersEl.appendChild(q);
q.classList.add("answer");
q.appendChild(qText);
q.addEventListener("click", (event) => {
cardInnerEl.style.pointerEvents = "none";
if (q.textContent === obj.answers[obj.correctIndex]) {
q.classList.toggle("correct");
} else {
q.classList.toggle("wrong");
}
setTimeout(function () {
removeCard();
waitMessage.style.display = "";
}, 1050);
return false;
});
};
for (var i = 0; i < obj.answers.length; i++) {
createAnswers(obj, i);
}
cardInnerEl.style.display = "";
}
waitMessage.style.display = "";
})(window.IVSPlayer);
/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. */
/* SPDX-License-Identifier: MIT-0 */
/* Reset */
*,*::before,*::after{box-sizing:border-box}ul[class],ol[class]{padding:0}body,h1,h2,h3,h4,p,ul[class],ol[class],figure,blockquote,dl,dd{margin:0}html{scroll-behavior:smooth}body{min-height:100vh;text-rendering:optimizeSpeed;line-height:1.5}ul[class],ol[class]{list-style:none}a:not([class]){text-decoration-skip-ink:auto}img{max-width:100%;display:block}article>*+*{margin-top:1em}input,button,textarea,select{font:inherit}#media (prefers-reduced-motion:reduce){*{animation-duration:0.01ms!important;animation-iteration-count:1!important;transition-duration:0.01ms!important;scroll-behavior:auto!important}}
/* Variables */
:root {
--radius: 12px;
}
/* Style */
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
body {
overflow: hidden;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif;
user-select: none;
}
#app {
background: #334273;
height: 100%;
}
.inner {
max-width: 1080px;
display: flex;
flex-direction: column;
position: relative;
align-items: stretch;
margin: 0 auto;
padding: 40px;
}
.player-wrapper {
width: 100%;
position: relative;
overflow: hidden;
transform: translate3d(0, 0, 0);
backface-visibility: hidden;
border-radius: var(--radius);
box-shadow: 0 6px 30px rgba(0, 0, 0, 0.3);
z-index: 1;
}
.aspect-spacer {
padding-bottom: 56.25%;
}
.el-player {
width: 100%;
height: 100%;
position: absolute;
top: 0;
background: #000;
border-radius: var(--radius);
}
video {
width: 100%;
border-radius: var(--radius);
background: #000;
}
.quiz-wrap {
min-height: 460px;
position: relative;
transition: all 0.25s ease-in;
}
.card {
margin: 0 20px;
padding: 20px;
position: absolute;
left: 0;
right: 0;
background: #fff;
border-radius: 20px;
box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.1);
transition: all 1s cubic-bezier(1, -0.56, 0, 1);
transform: translate3d(0, 0, 0) scale(1);
backface-visibility: hidden;
z-index: 1;
}
.card.drop {
opacity: 0;
transform: translate3d(0, 200px, -20px) scale(0.92);
}
h2 {
font-size: 25px;
text-align: center;
padding-bottom: 20px;
}
.answer {
height: 50px;
line-height: 50px;
font-size: 20px;
display: flex;
text-decoration: none;
border: 1px solid #d5dbdb;
border-radius: 50px;
padding: 0 24px;
margin: 10px 0;
background: #fafafa;
color: #545b64;
transition: all 0.05s ease-in-out;
}
.answer:hover {
background: #ebebebe0;
}
.answer:active {
background: #ff9900;
border: 1px solid #eb5f07;
color: #fff;
}
.answer.correct {
background: #25a702;
border: 1px solid #1d8102;
color: #fff;
animation: blink 0.45s infinite;
}
.answer.wrong {
background: #d13212;
border: 1px solid #b7290d;
color: #fff;
animation: blink 0.45s infinite;
}
#waiting {
top: 100px;
left: 0;
right: 0;
position: absolute;
display: flex;
align-items: center;
}
.waiting-text {
width: 100%;
display: block;
text-align: center;
font-size: 18px;
color: #d5dbdb;
}
.float {
transform: translateY(0px);
animation: float 6s ease-in-out infinite;
}
/* Utility - Position */
.pos-absolute {
position: absolute !important;
}
.pos-fixed {
position: fixed !important;
}
.pos-relative {
position: relative !important;
}
.top-0 {
top: 0 !important;
}
.bottom-0 {
bottom: 0 !important;
}
/* Utility - Width/Height */
.full-width {
width: 100%;
}
.full-height {
height: 100%;
}
/* Animations */
#keyframes blink {
50% {
opacity: 0.8;
}
}
#keyframes float {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(-20px);
}
100% {
transform: translateY(0px);
}
}
/* Mediaqueries */
#media (max-width: 767px) {
h2 {
font-size: 20px;
}
.card {
top: -20px;
}
}
#media (min-width: 767px) {
.card {
top: -25%;
}
}
<head>
<script src="https://content.jwplatform.com/libraries/oH2wJDod.js"></script>
<script src="https://player.live-video.net/1.11.0/amazon-ivs-jw-provider.min.js"></script>
</head>
<body>
<div id="app">
<div class="inner">
<!-- Player wrapper, forcing 16:9 aspect ratio -->
<div class="player-wrapper">
<div class="aspect-spacer"></div>
<div class="pos-absolute full-width full-height top-0">
<div id="video-player"></div>
</div>
</div>
<!-- Quiz UI -->
<div class="quiz-wrap">
<div id="waiting">
<span class="waiting-text float"
>Waiting for the next question</span
>
</div>
<div id="quiz" class="card drop">
<div id="card-inner">
<h2 id="question"></h2>
<div id="answers"></div>
</div>
</div>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
You are inside IIFE you can't declare outside of scope IIFE's are anonymous
Please read docume
const playbackUrl =
"https://fcc3ddae59ed.us-west-2.playback.live-video.net/api/video/v1/us-west-2.893648527354.channel.xhP3ExfcX8ON.m3u8";
const ivsConfig = {
playlist: [
{
file: playbackUrl,
type: "ivs"
}
]
};
const videoPlayer = document.getElementById("video-player");
const quizEl = document.getElementById("quiz");
const waitMessage = document.getElementById("waiting");
const questionEl = document.getElementById("question");
const answersEl = document.getElementById("answers");
const cardInnerEl = document.getElementById("card-inner");
(async (IVSPlayer) => {
try {
const playerInstance = jwplayer(videoPlayer).setup(ivsConfig);
playerInstance.on("providerPlayer", function (player) {
if (player) {
const { ivsEvents, ivsPlayer } = player;
ivsPlayer.addEventListener(
ivsEvents.PlayerEventType.TEXT_METADATA_CUE,
function (cue) {
const metadataText = cue.text;
// const position = player.getPosition().toFixed(2);
// position is under state.
const position = ivsPlayer.core.state.position.toFixed(2);
console.log(
`Player Event - TEXT_METADATA_CUE: "${metadataText}". Observed ${position}s after playback started.`
);
triggerQuiz(metadataText);
}
);
}
});
} catch (e) {
console.error(e);
}
function triggerQuiz(metadataText) {
let obj = JSON.parse(metadataText);
quizEl.style.display = "";
quizEl.classList.remove("drop");
waitMessage.style.display = "none";
cardInnerEl.style.display = "none";
cardInnerEl.style.pointerEvents = "auto";
while (answersEl.firstChild) answersEl.removeChild(answersEl.firstChild);
questionEl.textContent = obj.question;
let createAnswers = function (obj, i) {
let q = document.createElement("a");
let qText = document.createTextNode(obj.answers[i]);
answersEl.appendChild(q);
q.classList.add("answer");
q.appendChild(qText);
q.addEventListener("click", (event) => {
cardInnerEl.style.pointerEvents = "none";
if (q.textContent === obj.answers[obj.correctIndex]) {
q.classList.toggle("correct");
} else {
q.classList.toggle("wrong");
}
setTimeout(function () {
// removeCard(); is not defined. you must
// create it first
waitMessage.style.display = "";
}, 1050);
return false;
});
};
for (var i = 0; i < obj.answers.length; i++) {
createAnswers(obj, i);
}
cardInnerEl.style.display = "";
}
waitMessage.style.display = "";
})(window.IVSPlayer);
/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. */
/* SPDX-License-Identifier: MIT-0 */
/* Reset */
*,
*::before,
*::after {
box-sizing: border-box;
}
ul[class],
ol[class] {
padding: 0;
}
body,
h1,
h2,
h3,
h4,
p,
ul[class],
ol[class],
figure,
blockquote,
dl,
dd {
margin: 0;
}
html {
scroll-behavior: smooth;
}
body {
min-height: 100vh;
text-rendering: optimizeSpeed;
line-height: 1.5;
}
ul[class],
ol[class] {
list-style: none;
}
a:not([class]) {
text-decoration-skip-ink: auto;
}
img {
max-width: 100%;
display: block;
}
article > * + * {
margin-top: 1em;
}
input,
button,
textarea,
select {
font: inherit;
}
#media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
/* Variables */
:root {
--radius: 12px;
}
/* Style */
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
body {
overflow: hidden;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Ubuntu, "Helvetica Neue", sans-serif;
user-select: none;
}
#app {
background: #334273;
height: 100%;
}
.inner {
max-width: 1080px;
display: flex;
flex-direction: column;
position: relative;
align-items: stretch;
margin: 0 auto;
padding: 40px;
}
.player-wrapper {
width: 100%;
position: relative;
overflow: hidden;
transform: translate3d(0, 0, 0);
backface-visibility: hidden;
border-radius: var(--radius);
box-shadow: 0 6px 30px rgba(0, 0, 0, 0.3);
z-index: 1;
}
.aspect-spacer {
padding-bottom: 56.25%;
}
.el-player {
width: 100%;
height: 100%;
position: absolute;
top: 0;
background: #000;
border-radius: var(--radius);
}
video {
width: 100%;
border-radius: var(--radius);
background: #000;
}
.quiz-wrap {
min-height: 460px;
position: relative;
transition: all 0.25s ease-in;
}
.card {
margin: 0 20px;
padding: 20px;
position: absolute;
left: 0;
right: 0;
background: #fff;
border-radius: 20px;
box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.1);
transition: all 1s cubic-bezier(1, -0.56, 0, 1);
transform: translate3d(0, 0, 0) scale(1);
backface-visibility: hidden;
z-index: 1;
}
.card.drop {
opacity: 0;
transform: translate3d(0, 200px, -20px) scale(0.92);
}
h2 {
font-size: 25px;
text-align: center;
padding-bottom: 20px;
}
.answer {
height: 50px;
line-height: 50px;
font-size: 20px;
display: flex;
text-decoration: none;
border: 1px solid #d5dbdb;
border-radius: 50px;
padding: 0 24px;
margin: 10px 0;
background: #fafafa;
color: #545b64;
transition: all 0.05s ease-in-out;
}
.answer:hover {
background: #ebebebe0;
}
.answer:active {
background: #ff9900;
border: 1px solid #eb5f07;
color: #fff;
}
.answer.correct {
background: #25a702;
border: 1px solid #1d8102;
color: #fff;
animation: blink 0.45s infinite;
}
.answer.wrong {
background: #d13212;
border: 1px solid #b7290d;
color: #fff;
animation: blink 0.45s infinite;
}
#waiting {
top: 100px;
left: 0;
right: 0;
position: absolute;
display: flex;
align-items: center;
}
.waiting-text {
width: 100%;
display: block;
text-align: center;
font-size: 18px;
color: #d5dbdb;
}
.float {
transform: translateY(0px);
animation: float 6s ease-in-out infinite;
}
/* Utility - Position */
.pos-absolute {
position: absolute !important;
}
.pos-fixed {
position: fixed !important;
}
.pos-relative {
position: relative !important;
}
.top-0 {
top: 0 !important;
}
.bottom-0 {
bottom: 0 !important;
}
/* Utility - Width/Height */
.full-width {
width: 100%;
}
.full-height {
height: 100%;
}
/* Animations */
#keyframes blink {
50% {
opacity: 0.8;
}
}
#keyframes float {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(-20px);
}
100% {
transform: translateY(0px);
}
}
/* Mediaqueries */
#media (max-width: 767px) {
h2 {
font-size: 20px;
}
.card {
top: -20px;
}
}
#media (min-width: 767px) {
.card {
top: -25%;
}
}
<head>
<script src="https://content.jwplatform.com/libraries/oH2wJDod.js"></script>
<script src="https://player.live-video.net/1.11.0/amazon-ivs-jw-provider.min.js"></script>
</head>
<body>
<div id="app">
<div class="inner">
<!-- Player wrapper, forcing 16:9 aspect ratio -->
<div class="player-wrapper">
<div class="aspect-spacer"></div>
<div class="pos-absolute full-width full-height top-0">
<div id="video-player"></div>
</div>
</div>
<!-- Quiz UI -->
<div class="quiz-wrap">
<div id="waiting">
<span class="waiting-text float">Waiting for the next question</span>
</div>
<div id="quiz" class="card drop">
<div id="card-inner">
<h2 id="question"></h2>
<div id="answers"></div>
</div>
</div>
</div>
</div>
</div>
</body>

CSS transition works only with one element [duplicate]

This question already has answers here:
Why does querySelector only select the first element and how can I fix this?
(4 answers)
Closed 1 year ago.
I have been trying to make a working phone for a school project. In HTML. Now, I added a class with JS with the following:
document.querySelector(".app-content").classList.add("app-on");
Now, the class .app-on changes the width, height and font-size of my div. It has a transition built in. However, the width and height instantly pop up, while the font-size transitions just like i wanted.
.app-content is the class I am focusing on. The one I have added the animation to is the first one of that class to appear in the code
The full code for reference:
<html>
<head>
<meta charset="utf-8">
<link href="style.css" rel="stylesheet" type="text/css">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght#900&display=swap" rel="stylesheet">
</head>
<body onload="startTime()">
<!-- phone -->
<div id="phone-border">
<!-- screen -->
<div id="phone-screen">
<p id="time" style="font-weight: 600; font-size: 30px; float: left; color: white; padding: 10px;"></p>
<div id="app-container">
<div class="app-wrapper" style="z-index: 10000;">
<img src="https://img.icons8.com/ios/452/coronavirus--v1.png" class="app-icon" style="left: 10%; top 60%" onclick="openMA()">
<div class="app top-app left" href="#">Malware-Arten</div>
<div class="app-content" style="position: absolute; left: 0; color: black;">asdasdfasdfasdfasdf</div>
</div>
<div class="app-wrapper">
<img src="https://www.freeiconspng.com/thumbs/shield-png/shield-png-1.png" class="app-icon" style="right: 15%; top 60%" onclick="openS()">
<div class="app top-app right" href="#">Schutz</div>
<div class="app-content"></div>
</div>
<div class="app-wrapper">
<img src="https://www.freeiconspng.com/thumbs/youtube-logo-png/hd-youtube-logo-png-transparent-background-20.png" class="app-icon" style="left: 10%; bottom: 17%" onclick="openYT()">
<div class="app bottom-app left" href="#">Youtube-Info</div>
<div class="app-content"></div>
</div>
<div class="app-wrapper">
<img src="https://www.designbust.com/download/1024/png/email_icon_transparent512.png" class="app-icon" style="right: 15%; bottom: 17%" onclick="openM()">
<div class="app bottom-app right" href="#">E-Mail</div>
<div class="app-content"></div>
</div>
</div>
<div class="blackscreen">
</div>
</div>
<!-- /screen -->
<!-- homebutton -->
<div style="position: fixed;">
<button class="pushable homebutton" id="hb">
<div class="front home-front">
</div>
</button>
</div>
<!-- /homebutton -->
</div>
<!-- /phone -->
</body>
<script type="text/javascript" src="script.js"></script>
</html>
CSS here:
I have marked the class with a comment.
#import url('https://rsms.me/inter/inter.css');
html { font-family: 'Inter', sans-serif; }
body {
background: #2c2b30;
font-family: "Open Sans", Arial, Helvetica, sans-serif;
font-weight: 900;
color: #f58f7c;
letter-spacing: 1px;
display: flex;
align-items: center;
justify-content: center;
}
#phone-border{
width: 360px;
height: 630px;
background: #4f4f51;
margin: auto;
padding-top: 60px;
border-radius: 20px;
border-bottom: 13px solid #303030;
border-left: 13px solid #404040;
}
#phone-screen {
width: 92%;
height: 84%;
background: #f58f7c;
margin: auto;
position: relative;
}
#app-container {
position: absolute;
top: 50%;
-ms-transform: translateY(-50%);
transform: translateY(-50%);
width: 100%;
height: 63%;
}
.app-icon {
position: absolute;
width: 100px; height: 100px;
border-radius: 10px;
border: 3px solid #000;
-webkit-transition: all 0.1s ease-in;
-moz-transition: all 0.1s ease-in;
-o-transition: all 0.1s ease-in;
transition: all 0.1s ease-in;
}
.app-icon:hover {
transform: translateY(-10px);
}
.app {
color: #414b41;
margin: auto;
}
.top-app {
position: absolute;
bottom: 60%;
}
.bottom-app {
position: absolute;
bottom: 10%;
}
.left {
left: 6%;
}
.right {
right: 21%;
}
.app-content {
background: #404040;
font-size: 0;
-webkit-transition: all 0.2s ease-in;
transition: all 0.2s ease-in;
}
.app-on { /* -----------------------THIS-------------------------*/
font-size: 15px;
width: 100px;
height: 100px;
-webkit-transition: all 0.2s ease-in;
transition: all 0.2s ease-in;
}
.blackscreen {
width: 100%;
height: 100%;
background: #000;
margin: auto;
position: absolute;
z-index: 2;
transition: all 0.5s;
}
.fade {
background: transparent;
transition: 1s;
}
.phone-on {
box-shadow: 0px 0px 30px #f58f7c;
transition: 1.2s;
}
.homebutton {
width: 60px;
height: 60px;
background: #404040;
border-radius: 100px;
border: none;
padding: 0;
cursor: pointer;
outline-offset: 4px;
transition: all 0.5s;
position: fixed;
left: 48%;
top: 82%;
margin-top: 20px;
}
.home-front {
display: block;
padding-top: 60px;
border-radius: 100px;
font-size: 1.25rem;
background: #202020;
color: white;
transform: translateY(-6px);
position: relative;
left: 3px;
}
.homebutton:hover .front {
transform: translateY(-8px);
left: 4px;
transition: 0.08s;
}
.homebutton:active .front {
transform: translateY(-2px);
left: 1px;
transition: 0.08s;
}
JS here:
var on = false;
var homeButton = document.getElementById("hb");
homeButton.onclick = function(){
if (on==false) {
document.querySelector(".blackscreen").style.backgroundColor = "transparent";
document.getElementById("phone-screen").classList.add('phone-on');
on=true;
setTimeout(function(){document.querySelector(".blackscreen").style.zIndex = "-10";},500);
}
else if(on==true) {
console.log(123);
}
}
function openMA() {
console.log("Malware-Arten")
var malwareArten = true;
document.querySelector(".app-content").classList.add("app-on");
}
function openS() {
console.log("Schutz")
var schutz = true;
}
function openYT() {
console.log("YT")
var yt = true;
}
function openM() {
console.log("Mail")
var mail = true;
}
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
m = checkTime(m);
s = checkTime(s);
document.getElementById("time").innerHTML = h + ":" + m + ":" + s;
var t = setTimeout(startTime, 1000);
}
function checkTime(i) {
if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
document.querySelector only returns one element. You want to use document.querySelectorAll for multiple elements, along with a loop to do this.
document.querySelector(".app-content").forEach((ele) => ele.classList.add("app-on"));
The default width and height of a div is auto and you cannot transition from an auto property to a pixel value. Try adding width: 0; height: 0; to the .app-content class.

after click on `Open Modal` button. why it's disappear?

after click on Open Modal button. it's disappear . i did not see anything wrong with my code.
Code Example - Scenario
let nrSanckbar = (function(){
const modalContent = `<div class="nr-modal-container" class="modal">
<div class="modal-content">
<span class="close">×</span>
<p>Some text in the Modal..</p>
</div>
</div>`;
document.addEventListener("click",function(e){
e.preventDefault();
e.stopPropagation()
const modal = document.querySelector(".nr-modal-container");
if(e.target.classList.contains('close')){
console.log(e.target)
modal.classList.remove("visible");
modal.remove();
return false;
}
})
const shwoModal = function(){
document.body.innerHTML = modalContent;
const modal = document.querySelector(".nr-modal-container");
modal.classList.add("visible");
return false;
}
return {
deleteConfirm: function(data) {
shwoModal()
},
}
})();
document.addEventListener("click",function(e){
e.preventDefault();
e.stopPropagation()
if(e.target.classList.contains('open-modal-button')){
nrSanckbar.deleteConfirm()
}
})
.modal {
position: fixed;
z-index: 10;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
display: none;
}
/* Modal Content */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 50%;
border-radius: 5px;
box-shadow: 0 24px 38px 3px rgba(60, 75, 100, 0.14);
display:none;
}
.close {
color: #aaaaaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
.visible {
display: block;
}
.visible > .modal-content {
display: block;
-webkit-animation: scale .3s ease-out;
-moz-animation: scale .3s ease-out;
}
#-webkit-keyframes scale {
0% { opacity: 0; -webkit-transform: scale(1.3); }
100% { opacity: 1; -webkit-transform: scale(1); }
}
#-moz-keyframes scale{
0% { opacity: 0; -moz-transform: scale(1.3); }
100% { opacity: 1; -moz-transform: tscale(1);}
}
<button class="open-modal-button">Open Modal</button>
Your button is being removed due to document.body.innerHTML = modalContent; (as inner HTML contains the button)
You should be able to do something like document.body.innerHTML += modalContent;
Or: document.body.insertAdjacentHTML( 'beforeend', modalContent);

On reload, show loading html page and redirect to the correct page

I'm trying to build a website and am facing serious trouble with the following. So let's say that the user reloads or clicks on a link to another page on the site, I want to show the loading page before we arrive at the page we are looking to go to. Here's my code and I really am having some trouble. Any suggestions would be much appreciated, but I would really like to do this without adding or removing too much. I tried to play around with the javascript but alas, it did not work. If you have suggestions about that, please let me know as well. Thank you so much!
index.html
<!DOCTYPE html>
<meta charset = 'UTF-8'>
<meta name = "viewport" content = "width = device-width, initial-scale = 1">
<link rel = "stylesheet" href = "styles.css">
<link rel = "stylesheet" href = "animate.css">
<head>
<script src = "scripts.js"></script>
<a href="#">
<img class = "animated zoomIn" src = "image.png">
</a>
<div id = "navbar" class = "overlay">
×
<div class = "overlay-content">
Home
About Us
Gallery
The Podcast
More
Merch
Appearances
Contact Us
We're Hiring!
<div class = "line"></div>
</div>
</div>
<div class = "animated slideInLeft" style = "text-align: center;">
<span style="font-size:30px;cursor:pointer;" onclick="openNav()">
☰ Open Me!
</span>
</div>
</head>
<body>
<h1 style ="text-align:center">
</body>
styles.css
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
#font-face {
font-family: Paintball;
font-weight: bold;
src: url(paintball_web.woff);
}
/* Header Properties */
body{
background-color: navy;
font-family: Paintball;
}
img {
display: block;
margin-left: auto;
margin-right: auto;
width: 40%;
}
/*Navigation Bar Properties */
.overlay {
height: 100%;
width: 0;
position: absolute;
z-index: 1;
top: 0;
text-align: center;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0, 0.9);
overflow-x: hidden;
transition: 0.5s;
}
.overlay-content {
position: relative;
top: 25%;
width: 100%;
text-align: center;
margin-top: 30px;
}
.overlay a {
padding: 8px;
text-decoration: none;
font-size: 36px;
color: #818181;
display: block;
transition: 0.3s;
}
.overlay a:hover, .overlay a:focus {
color: #f1f1f1;
}
.overlay .closebtn {
position: absolute;
top: 20px;
right: 45px;
font-size: 60px;
}
div span{
color:#42f459;
}
/* Loader Properties */
.wrap {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.text {
color: #42f459;
display: inline-block;
margin-left: 5px;
}
.bounceball {
position: relative;
display: inline-block;
height: 37px;
width: 15px;
}
.bounceball:before {
position: absolute;
content: '';
display: block;
top: 0;
width: 15px;
height: 15px;
border-radius: 50%;
background-color: #42f459;
-webkit-transform-origin: 50%;
transform-origin: 50%;
-webkit-animation: bounce 500ms alternate infinite ease;
animation: bounce 500ms alternate infinite ease;
}
#-webkit-keyframes bounce {
0% {
top: 30px;
height: 5px;
border-radius: 60px 60px 20px 20px;
-webkit-transform: scaleX(2);
transform: scaleX(2);
}
35% {
height: 15px;
border-radius: 50%;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
100% {
top: 0;
}
}
#keyframes bounce {
0% {
top: 30px;
height: 5px;
border-radius: 60px 60px 20px 20px;
-webkit-transform: scaleX(2);
transform: scaleX(2);
}
35% {
height: 15px;
border-radius: 50%;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
100% {
top: 0;
}
}
Welcome.html
<!DOCTYPE html>
<meta charset = 'UTF-8'>
<meta http-equiv="Refresh" content="4; url=index.html" />
<meta name = "viewport" content = "width = device-width, initial-scale = 1">
<link rel = "stylesheet" href = "styles.css">
<div class="wrap">
<div class="loading">
<div class="bounceball"></div>
<div class="text">NOW LOADING</div>
</div>
</div>
scripts.js
function openNav() {
document.getElementById("navbar").style.width = "100%";
}
function closeNav() {
document.getElementById("navbar").style.width = "0%";
}
document.addEventListener('DOMContentLoaded',function(){
if(document.readyState === 'complete'){
alert("loaded");
}
}
)
document.addEventListener('readystatechange',function(){
if (document.readystate === 'loading'){
window.location = "Welcome.html";
}
}
)

Categories