What do I have mistake about setInterval in JS - javascript

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>

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>

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>

Replacing setInterval with setTimeout should fix your problem.
setTimeout(() => { removeNotification(); }, sec);
you can learn more from here: setTimeout or setInterval?

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.

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>

Related

Why last function is applying to other elements also on 2nd change

I have created a color changer for different properties like border & background for elements.
Color changing 1 at a time but issue occurs when I click on next element , now the color of both elements changes (on next click) . Is there a way to change only 1 at a time .
The method to solve this can be creating a color-picker with each click and remove when work is done but if possible can the solution be regarding the input color-picker in html
To see the issue :
1)Click on any circle & change its color (works fine)
2)Now click on any other circle and try to change its color
Issue seen : Now on 2nd step both circles color changes at same time
var restyleBG = document.getElementsByClassName("restyleBackground")
for (let i = 0; i < restyleBG.length; i++) {
restyleBG[i].addEventListener('click', changeBGcolor)
function changeBGcolor() {
event.stopPropagation()
var colorPicker = document.getElementById("colorClock");
colorPicker.click();
colorPicker.addEventListener('input', function() {
var colorPickerVal = colorPicker.value;
restyleBG[i].style.backgroundColor = colorPickerVal;
})
}
}
#clockStyleCircle {
position: absolute;
width: 16vw;
height: 16vw;
text-align: center;
padding: 0%;
top: 28.5%;
left: 28.5%;
border-radius: 50%;
border: 3px solid black;
background-color: rgb(255, 233, 35);
z-index: 1;
}
#clockOuterCircle {
display: flex;
justify-content: center;
align-items: center;
width: 42vw;
height: 42vw;
margin: auto;
border-radius: 50%;
border: 4px solid rgb(255, 62, 62);
background-color: rgb(253, 133, 133);
user-select: none;
}
#another-circle {
width: 50px;
height: 50px;
border-radius: 50%;
border: 4px green solid;
background-color: blue;
position: absolute;
top: 20px;
left: 20px;
}
.colour-picker {
display: none;
}
<body>
<input type="color" name="colorClock" id="colorClock">
<div id="clockOuterCircle" class="restyleBackground">
<div id="clockStyleCircle" class="restyleBackground"></div>
</div>
<!-- another circle -->
<div id="another-circle" class="restyleBackground"></div>
<!-- ... -->
</body>
Thanks for help in advance
What is going on ?
Your problem here is that for every time you click on a circle you add an EventListener to your colorPicker which then changes the color of the circle. So every time you change the value of the colorPicker, the circles that got clicked on change their color.
How to achieve what you want
You could try to remove the EventListener after the change happened, but this isn't good practice. What you should do is create a global variable that holds the index to the current circle of the circles array that got clicked on and add an EventListener to the input element, that changes the color of the circle with the index of that reference variable. Below you can see the code.
var restyleBG = document.getElementsByClassName("restyleBackground")
let current = 0;
var colorPicker = document.getElementById("colorClock");
colorPicker.addEventListener('input', function() {
restyleBG[current].style.backgroundColor = colorPicker.value;
})
for (let i = 0; i < restyleBG.length; i++) {
restyleBG[i].addEventListener('click', changeBGcolor)
function changeBGcolor() {
event.stopPropagation()
colorPicker.click();
current = i;
}
}
#clockStyleCircle {
position: absolute;
width: 16vw;
height: 16vw;
text-align: center;
padding: 0%;
top: 28.5%;
left: 28.5%;
border-radius: 50%;
border: 3px solid black;
background-color: rgb(255, 233, 35);
z-index: 1;
}
#clockOuterCircle {
display: flex;
justify-content: center;
align-items: center;
width: 42vw;
height: 42vw;
margin: auto;
border-radius: 50%;
border: 4px solid rgb(255, 62, 62);
background-color: rgb(253, 133, 133);
user-select: none;
}
#another-circle {
width: 50px;
height: 50px;
border-radius: 50%;
border: 4px green solid;
background-color: blue;
position: absolute;
top: 20px;
left: 20px;
}
.colour-picker {
display: none;
}
<body>
<input type="color" name="colorClock" id="colorClock">
<div id="clockOuterCircle" class="restyleBackground">
<div id="clockStyleCircle" class="restyleBackground"></div>
</div>
<!-- another circle -->
<div id="another-circle" class="restyleBackground"></div>
<!-- ... -->
</body>
As I said in comments on every click you were adding new event listeners so after the second click there you have more than one event registered. so from the second click, your input Listener will call all previous color changes, that's why it is changing the color of all 3 circles.
I have removed the listener after every color change so this code works fine
Check the console once to get the listener calls, also check by removing the "removeEventListener" and check how many "input event called" will appear after changing color if all three circles (this will help to understand the problem in your code )
Also, you may not be needed to add an input evenlistener inside the loop, I have approached same to understand the problem in your code
You can add eventListner outside the loop
So that you may not need to remove it
var restyleBG = document.getElementsByClassName("restyleBackground")
var colorPicker = document.getElementById("colorClock");
var element;
for (let i = 0; i < restyleBG.length; i++) {
restyleBG[i].addEventListener('click', ()=> changeBGcolor(restyleBG[i]))
}
function changeBGcolor(restyle) {
event.stopPropagation()
colorPicker.click();
element = restyle
colorPicker.addEventListener('input', respond)
}
function respond() {
var colorPickerVal = colorPicker.value;
console.log('input event called')
element.style.backgroundColor = colorPickerVal;
}
colorPicker.addEventListener('change',function (){
console.log('input event removed')
colorPicker.removeEventListener('input', respond)
})
#clockStyleCircle {
position: absolute;
width: 16vw;
height: 16vw;
text-align: center;
padding: 0%;
top: 28.5%;
left: 28.5%;
border-radius: 50%;
border: 3px solid black;
background-color: rgb(255, 233, 35);
z-index: 1;
}
#clockOuterCircle {
display: flex;
justify-content: center;
align-items: center;
width: 42vw;
height: 42vw;
margin: auto;
border-radius: 50%;
border: 4px solid rgb(255, 62, 62);
background-color: rgb(253, 133, 133);
user-select: none;
}
#another-circle {
width: 50px;
height: 50px;
border-radius: 50%;
border: 4px green solid;
background-color: blue;
position: absolute;
top: 20px;
left: 20px;
}
.colour-picker {
display: none;
}
<body>
<input type="color" name="colorClock" id="colorClock">
<div id="clockOuterCircle" class="restyleBackground" >
<div id="clockStyleCircle" class="restyleBackground" ></div>
</div>
<!-- another circle -->
<div id="another-circle" class="restyleBackground" ></div>
<!-- ... -->
</body>

How to detect iOS and show banner once in pure Javascript?

This script works to show a banner on all platforms, but I would like it to show only when it detects iOS devices.
<---- Good Script------->
const cookieBanner = document.querySelector(".cookie-banner");
const cookieButton = document.querySelector(".cookie-btn");
cookieButton.addEventListener("click", () => {
cookieBanner.classList.remove("active");
localStorage.setItem("cookieBannerDisplayed", "true");
});
setTimeout(() => {
if (!localStorage.getItem("cookieBannerDisplayed")) {
cookieBanner.classList.add("active");
}
}, 2000);
I tried doing this below but it didn't work. Instead, it completely no longer works on any platform; not on Safari iOS, Safari, Chrome nor Firefox.
<---- Bad Script------->
const cookieBanner = document.querySelector(".cookie-banner");
const cookieButton = document.querySelector(".cookie-btn");
var t = window.navigator.userAgent,
a = window.navigator.platform;
cookieButton.addEventListener("click", () => {
cookieBanner.classList.remove("active");
localStorage.setItem("cookieBannerDisplayed", "true");
});
setTimeout(() => {
if (!localStorage.getItem("cookieBannerDisplayed")) && if (!["iPhone", "iPad", "iPod"].indexOf(a)) {
cookieBanner.classList.add("active");
}
}, 2000);
Edit: I'm including the CSS code that it 'active'ates.
What this does is show the banner sliding into the users view:
.cookie-banner{
display: flex;
flex-direction: row;
background-color:#282828;
opacity: 0.90;
color: #fff;
width: 100%;
position: fixed;
top: -100%;
right: 0;
z-index: 100;
align-items: center;
justify-content: start;
font-size: 0.875rem;
line-height: 1.5;
font-weight: 400;
box-shadow: rgba(255, 255, 255, 0.05) 0px -1px 0px 0px;
padding: 1rem 1.25rem 1rem 18px;
transition: 400ms;
}
.cookie-banner a{
color: #f5f6fa;
text-decoration: underline;
}
.cookie-btn {
display: inline-flex;
background-color: transparent;
border: 1px solid #fff;
color: #f5f6fa;
padding: .2rem 1rem;
font-size: .875rem;
margin-bottom: 9px;
margin-left: 30px;
border-radius: 50px;
cursor: pointer;
}
.cookie-banner.active {
top: 0;
}
Below is the main page that the user is looking at basically the body is normally filled with article words.
On the main page I have this
<head>
<link rel="stylesheet" type="text/css" href="assets/css/ios-banner.css">
</head>
<body>
div class="cookie-banner">
<p> We use cookies to provide you with the best experience on our site. Learn More </p>
<button class="cookie-btn">Okay</button>
</div>
<script src="assets/js/ios-banner.js"></script>
</body>
Any ideas what I'm doing wrong?
Your issue was you had bad logic in your set timeout callback, and you have not got a proper opening tag to your banner div in the html you list.
Also in general try to use good naming practices instead of variable names like 't' and 'a' as it will make your code hard to read and therefore hard to understand.
Here is what worked for me:
The CSS (unchanged)
.cookie-banner {
display: flex;
flex-direction: row;
background-color: #282828;
opacity: 0.90;
color: #fff;
width: 100%;
position: fixed;
top: -100%;
right: 0;
z-index: 100;
align-items: center;
justify-content: start;
font-size: 0.875rem;
line-height: 1.5;
font-weight: 400;
box-shadow: rgba(255, 255, 255, 0.05) 0px -1px 0px 0px;
padding: 1rem 1.25rem 1rem 18px;
transition: 400ms;
}
.cookie-banner a {
color: #f5f6fa;
text-decoration: underline;
}
.cookie-btn {
display: inline-flex;
background-color: transparent;
border: 1px solid #fff;
color: #f5f6fa;
padding: .2rem 1rem;
font-size: .875rem;
margin-bottom: 9px;
margin-left: 30px;
border-radius: 50px;
cursor: pointer;
}
.cookie-banner.active {
top: 0;
}
The HTML, used ids for selectors and fixed the opening div tag error
<div id="cookie-banner-id" class="cookie-banner">
<p>
We use cookies to provide you with the best experience on our site.
<a href="https://somewebsitehere.website/privacy.php">
Learn More
</a>
</p>
<button id="cookie-btn-id" class="cookie-btn">Okay</button>
</div>
The JS
const cookieBanner = document.getElementById("cookie-banner-id");
const cookieButton = document.getElementById("cookie-btn-id");
const userAgentValue = navigator.userAgent;
let cookieBannerDisplayed = false;
let activeClassAdded = false; // so we only add active once
cookieButton.addEventListener("click", () => {
cookieBanner.classList.remove("active");
localStorage.setItem("cookieBannerDisplayed", true);
});
setTimeout(() => {
if (!localStorage.getItem("cookieBannerDisplayed")){
["iPhone", "iPad", "iPod"].forEach((targetBrowserName) => {
if (userAgentValue.includes(targetBrowserName) && !activeClassAdded) {
cookieBanner.classList.add("active");
activeClassAdded = true;
}
});
}
}, 2000);
When testing you may need to clear local storage for each test run, else switch out the local storage for a local variable.

can I use checkbox which is in div with Eventlistener?

"use strict";
const diaryInput = document.querySelector(".writing");
const titleInput = document.querySelector(".title");
const submitButton = document.querySelector(".dsubmit");
const indexList = document.querySelector(".womb");
const inputTime = document.querySelector(".clock");
const selectAll = document.querySelector(".select");
const unselectAll = document.querySelector(".unselect");
const deleteIndex = document.querySelector(".delete");
submitButton.addEventListener("click", transferDiary);
selectAll.addEventListener("click", selectAllindex);
unselectAll.addEventListener("click", unselectAllindex);
deleteIndex.addEventListener("click", deleteDiaryIndex);
let layout_no = 0;
function transferDiary(e) {
e.preventDefault();
const indexLayout = document.createElement("div");
indexLayout.classList.add("indexlayout");
indexLayout.id = "indexlayout-" + layout_no;
const diaryIndex = document.createElement("div");
diaryIndex.classList.add("invisible");
diaryIndex.innerText = diaryInput.value;
saveLocalDiary(diaryInput.value);
const diaryTitle = document.createElement("div");
diaryTitle.classList.add("index");
const m = new Array(
"JAN.",
"FEB.",
"MAR.",
"APR.",
"MAY",
"JUN.",
"JUL.",
"AUG",
"SEPT.",
"OCT.",
"NOV.",
"DEC."
);
const years = date.getFullYear();
const months = date.getMonth();
const d = new Array(
"Sun.",
"Mon.",
"Tues.",
"wed.",
"Thurs.",
"Fri.",
"Sat."
);
const days = date.getDay();
const today = date.getDate();
diaryTitle.innerHTML = `<input type='checkbox' name='indexchild' value='' class="indexchild" >${m[months]} ${today} ${years} ${d[days]} -${titleInput.value}</>`;
indexLayout.appendChild(diaryTitle);
diaryTitle.appendChild(diaryIndex);
indexList.appendChild(indexLayout);
const wayBackHome = document.getElementById("indexlayout-" + layout_no);
wayBackHome.addEventListener("click", bringBackIndex);
layout_no++;
}
function selectAllindex(e) {
e.preventDefault();
const checkboxes = document.querySelectorAll("input[type=checkbox]");
for (const cb of checkboxes) {
cb.checked = true;
}
}
function unselectAllindex(e) {
e.preventDefault();
const checkboxes = document.querySelectorAll("input[type=checkbox]");
for (const cb of checkboxes) {
cb.checked = false;
}
}
function deleteDiaryIndex(i) {
i.preventDefault();
const checkboxes = document.querySelectorAll("input[type=checkbox]");
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked) {
removeDiv(checkboxes[i]);
removeLocalDiary(checkboxes[i]);
}
}
}
function removeDiv(d) {
console.log(d.parentElement.parentElement);
console.log(d.parentElement.parentElement[1]);
d.parentElement.parentElement.remove();
}
function bringBackIndex(e) {
e.preventDefault();
const bringEssence = e.target.getElementsByClassName("invisible");
diaryInput.value = bringEssence[0].innerHTML.replace(
/\s?(<br\s?\/?>)\s?/g,
"\r\n"
);
}
function saveLocalDiary(todo) {
//check ---- HEy Do I already have thing in localstorage?
let diary;
if (localStorage.getItem("diary") === null) {
diary = [];
} else {
diary = JSON.parse(localStorage.getItem("diary"));
}
diary.push(todo);
localStorage.setItem("diary", JSON.stringify(diary));
}
function removeLocalDiary(todo) {
let diary;
if (localStorage.getItem("diary") === null) {
diary = [];
} else {
diary = JSON.parse(localStorage.getItem("diary"));
}
const todoIndex = todo.children.innerText;
diary.splice(diary.indexOf(todoIndex), 1);
localStorage.setItem("diary", JSON.stringify(diary));
}
:root {
--page1-color: #20bf6b;
--page2-color: #f7b731;
--page3-color: #4b7bec;
--text-color: white;
}
html {
font-size: 62.5%;
/* 10px=1rem */
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: sans-serif;
}
.page3 {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: var(--page3-color);
width: 70%;
min-width: 600px;
box-shadow: 9px 9px 9px rgb(126, 124, 124),9px 9px 9px rgb(126, 124, 124);
}
.dlayout {
min-height: 90vh;
max-height: 90vh;
border: 1px solid var(--text-color);
display: flex;
}
.dtitle {
min-height: 10%;
border-bottom: 1px solid var(--text-color);
}
.dindex {
min-width: 10vw;
max-width: 15vw;
border-right: 1px solid var(--text-color);
display: flex;
flex-direction: column;
justify-content: space-between;
}
.diary {
min-width: 50vw;
display: flex;
flex-direction: column;
}
.submit {
display: flex;
flex-direction: row;
height: 10%;
border-bottom: 1px solid var(--text-color);
}
.submitime {
padding: 25px 0 0 15px;
color: var(--text-color);
min-width: 50%;
font-size: 3rem;
font-weight: 300;
}
.submitarea {
padding: 20px 0 0 0;
min-width: 40%;
color: var(--text-color);
font-size: 3rem;
letter-spacing: 3px;
font-weight: 300;
}
.title {
background-color: var(--page3-color);
border: 1px dashed var(--text-color);
font-size: 3rem;
outline: none;
height: 40px;
width: 200px;
letter-spacing: 3px;
font-weight: 300;
}
.dsubmit {
margin-top: 10px;
height: 30px;
width: 30px;
background-color: var(--page3-color);
border: none;
border-radius:50%;
cursor: pointer;
}
.dtitle {
color: var(--text-color);
text-align: center;
display: table;
font-size: 3rem;
font-weight: 300;
letter-spacing: 20px;
/* 자간 */
}
p {
display: table-cell;
vertical-align: middle;
}
.writing {
background-color: var(--page3-color);
border: none;
height: 90%;
color: var(--text-color);
font-size: 2.5rem;
letter-spacing: 3px;
font-weight: 100;
}
textarea::placeholder {
color: var(--text-color);
opacity: 0.5;
}
textarea{
resize: none;
}
.indexlayout {
color: var(--text-color);
text-align: center;
font-size: 1.5rem;
border: 1px solid var(--text-color);
margin:5px;
}
.invisible {
display:none ;
}
.womb{
overflow: scroll;
}
.selector{
color: var(--text-color);
width: 100%;
border:none;
border-top: 1px solid var(--text-color);
min-height: 5%;
background-color: var(--page3-color);
outline: none;
font-size: 3rem;
letter-spacing: 8px;
font-weight: 300;
}
.index{
word-break: break-all;
}
.indexchild{
}
.selector:hover{
color:var(--page3-color);
background-color: var(--text-color);
}
.dsubmit:hover{
box-shadow: -3px -3px 3px rgb(172, 172, 172), 3px 3px 3px rgb(237, 237, 237),;
transition: 0.3s;
}
.indexlayout:hover{
color:var(--page3-color);
background-color: var(--text-color);
}
<section class="page3">
<div class="dlayout">
<form id="indexo" name="indexi" class="dindex">
<div class="dtitle"><p>Diary</p></div>
<div class="womb"></div>
<div class="buttons">
<button class="selector select" value="selectall">Select All</button>
<button class="selector unselect" value="unselectall">Unselect All</button>
<button class="selector delete" value="delete">Delete</button>
</div>
</form>
<div class="diary">
<div class="submit">
<div class="submitime clock"></div>
<form class="submitarea">
Title: <input type="text" class="title" />
<button class="dsubmit"><img src="./arrow-circle-right-solid.svg" alt=""></button>
</form>
</div>
<textarea class="writing" placeholder=" shit something..."></textarea>
</div>
</div>
</section>
Hello, I am struggling code above. It is a quite simple diary, the right side has a textarea
tag so you can write your diary and also has a transfer button so you push it, left side is gonna have an index of what you wrote. and I also added a checkbox on the index so you can select/unselect/delete them all at once. if perfectly works fine until I added another function. I added Eventlistener(handler is click) on the index(div .indexlayout), when you click the index it is gonna bring back what you wrote into the textarea tag.
const wayBackHome = document.getElementById("indexlayout-" + layout_no);
wayBackHome.addEventListener("click", bringBackIndex);
It works also okay. so I was quite satisfied. However, a little while later, I found that checkboxes don't work ever since added a new function!!
to be specific, select/unselect All buttons still work and I can check checkboxes with those, but I cannot select checkboxes individually :/
I think it is because I added an event on div which is a parent of a checkbox.
But, not gonna lie, I had no idea how to solve this. I tried "wayBackHome.innerText" or even added event to other div but it didn't work. Could you tell me what I missed and How do I fix it please?
thx!

How do I make a cleaner JS color flipper without muddying the DOM?

I built a random color flipper with setInterval and Math.random.
Here's the console warning from my current approach:
"Expected color but found ‘#3acf4’. Error in parsing value for ‘color’. Declaration dropped."
I think my logic may be backwards somewhere.
Does anyone perhaps know how I can make this JS a bit more terse and clear the warning?
Please and thanks!
// grabbing elements
const wrap = document.querySelector('.page-wrap');
const infinite = document.querySelector('.infinite-button');
const reset = document.querySelector('.reset-button');
let randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
let interval;
// starting color flip
infinite.addEventListener('click', colorRandomizer);
// reset color flip
reset.addEventListener('click', colorStopper);
// timing color flips
function colorRandomizer() {
interval = setInterval(function() {
colorMetrics();
}, 300);
}
// stopping color flips
function colorStopper() {
clearInterval(interval);
wrap.style.backgroundColor = '';
}
// refreshing random colors
function inifiniteColor() {
if (randomColor != '') {
randomColor = '';
} else if (randomColor == '') {
randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
}
return randomColor;
}
// monkey around with the dom
function colorMetrics() {
if (wrap.style.backgroundColor == '') {
wrap.style.backgroundColor = inifiniteColor();
} else if (wrap.style.backgroundColor == '#randomColor') {
wrap.style.backgroundColor = inifiniteColor();
} else {
wrap.style.backgroundColor = '';
}
}
.page-wrap {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
min-height: 100vh;
margin: 0;
}
.infinite-button {
background: transparent;
border: 2px solid dimGrey;
border-radius: 5px;
display: flex;
justify-content: center;
align-items: center;
width: 100px;
margin-bottom: 25px;
padding: 5px 0;
cursor: pointer;
}
.infinite-button:hover {
color: yellowGreen;
background: dimGrey;
border-color: yellowGreen;
}
.infinite-dood {
font-size: 40px;
margin: 0;
}
.reset-button {
color: indianRed;
background: transparent;
border: 2px solid indianRed;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
width: 25px;
height: 25px;
margin: 0;
padding: 25px;
cursor: pointer;
}
.reset-button:hover {
color: white;
background: indianRed;
border-color: darkRed;
}
.reset-dood {
font-size: 25px;
}
<div class="page-wrap">
<button class="infinite-button">
<p class="infinite-dood">
∞
</p>
</button>
<button class="reset-button">
<p class="reset-dood">
X
</p>
</button>
</div>
Like #Heretic Monkey said... "The color produced is only 5 characters and colors are required to be 6 characters."
I played your CodePen for many minutes and that error didn't show... But anyway, you could try this:
function inifiniteColor() {
if (randomColor != '') {
randomColor = '';
} else if (randomColor == '') {
randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
// If randomColor length is not 7 (# + 6 hex), complete with zeros
if(randomColor.length<7){
randomColor = randomColor + "0".repeat(7-randomColor.length)
}
}
return randomColor;
}
// grabbing elements
const wrap = document.querySelector('.page-wrap');
const infinite = document.querySelector('.infinite-button');
const reset = document.querySelector('.reset-button');
let interval;
// starting color flip
infinite.addEventListener('click', () => {
interval = setInterval(() => {
wrap.style.backgroundColor =
('#' + Math.floor(Math.random() * 16777215).toString(16));
}, 300);
});
// reset color flip
reset.addEventListener('click', () => {
clearInterval(interval);
wrap.style.backgroundColor = '';
});
.page-wrap {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
min-height: 100vh;
margin: 0;
}
.infinite-button {
display: flex;
justify-content: center;
align-items: center;
width: 100px;
margin: 25px;
padding: 5px;
background: transparent;
border: 2px solid dimGrey;
border-radius: 5px;
cursor: pointer;
}
.infinite-button:hover {
color: yellowGreen;
background: dimGrey;
border-color: yellowGreen;
}
.infinite-dood {
font-size: 40px;
margin: 0;
}
.reset-button {
color: indianRed;
background: transparent;
border: 2px solid indianRed;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
width: 25px;
height: 25px;
margin: 0;
padding: 25px;
cursor: pointer;
}
.reset-button:hover {
color: white;
background: indianRed;
border-color: darkRed;
}
.reset-dood {
font-size: 25px;
}
<div class="page-wrap">
<button class="infinite-button">
<p class="infinite-dood">
∞
</p>
</button>
<button class="reset-button">
<p class="reset-dood">
X
</p>
</button>
</div>
Something like this should do the trick

JavaScript - Game. Algorithm to match two variables generate by random generator

I have problem with my algorithm in simple game.
Game Rules:
Match color NAME (choose one on the bottom) with COLOR of TEXT (on the top).
If none of the two bottom names match than click NEXT.
So the problem is that first correct match gives in console "GOOD" but second , third and any after, even if there is correct match in console I have firstly always "WRONG" and just after that I have "GOOD".
This is a picture with the problem described
It seems like the script remember past random numbers and match current result with them, because after few matches the score pointer raise very quickly (ex. 20 points in one time).
I will be happy to hear from you how can I fix this.
Thank you for any help !
Here you have link to codepen:
http://codepen.io/anon/pen/bWGGga
"use strict"
/*Start Container*/
/* var startContainer = document.getElementById("start_container");
var letsPlay = document.getElementById("start_game"); */
/* letsPlay.addEventListener("click", openTheGame); */
function openTheGame(){
setInterval(startGame, 3000);
};
openTheGame();
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var btn3 = document.getElementById("btn3");
var showColor = document.getElementById("show_color");
//SCORE
var score = document.getElementById("score");
var gameContainer = document.getElementById("game_container");
var gameOverContainer = document.getElementById("game_over_container");
/*Array of Colors*/
var arrCol = ["GREEN", "RED", "YELLOW", "BLUE", "ORANGE", "PURPLE"]
//Array from buttons texts to draw Show Color
var arrShowColor = [];
function startGame(){
/*BUTTONS TEXT & COLOR*/
btn1.addEventListener("click", matchColor1);
btn2.addEventListener("click", matchColor2);
btn3.addEventListener("click", matchColor3);
//draw numbers for buttons texts & colors
var randomBtn1Num = Math.floor(Math.random() * 3);
var randomBtn2Num = Math.floor(Math.random() * 3)+3;
var randomBtn3Num = Math.floor(Math.random() * 6);
//Buttons text (next button always "next")
btn1.innerHTML = arrCol[randomBtn1Num];
btn2.innerHTML = arrCol[randomBtn2Num];
//Buttons Color from random_color class
btn1.className = "random_color" + randomBtn2Num;
btn2.className = "random_color" + randomBtn3Num;
btn3.className = "random_color" + randomBtn1Num;
/*SHOW TEXT & COLOR*/
//Array from buttons texts to draw Show Color
arrShowColor[0] = randomBtn1Num;
arrShowColor[1] = randomBtn2Num;
arrShowColor[2] = randomBtn3Num;
console.log(arrShowColor);
//Show color
var randomShowColorNum = Math.floor(Math.random()*3);
var randomShowColor = arrShowColor[randomShowColorNum];
showColor.className = "random_color" + randomShowColor;
console.log(randomShowColor);
//Show text
var randomShowText = Math.floor(Math.random() * 6);
showColor.innerHTML = arrCol[randomShowText];
/*CLICK BUTTON - IF MATCH COLORS*/
function matchColor1(){
if( randomBtn1Num == randomShowColor) {
console.log("GOOD");
score.innerHTML ++;
} else {
console.log("WRONG");
/*gameContainer.style.display = "none";
gameOverContainer.style.display = "inline-block";*/
}
};
function matchColor2(){
if( randomBtn2Num == randomShowColor) {
console.log("GOOD");
score.innerHTML ++;
} else {
console.log("WRONG");
/*gameContainer.style.display = "none";
gameOverContainer.style.display = "inline-block";*/
}
};
function matchColor3(){
if(randomBtn1Num != randomShowColor && randomBtn2Num != randomShowColor){
console.log("GOOD");
score.innerHTML ++;
} else {
console.log("WRONG");
/*gameContainer.style.display = "none";
gameOverContainer.style.display = "inline-block";*/
}
};
/*Finish startGame*/
};
/*Main Styles*/
body {
background-image: url()
}
h4 {
color: #2626e6;
}
/*Main Container Styles*/
#main_container {
width:100%;
text-align:center;
}
/*Start Container Styles*/
#start_container {
position: relative;
display: inline-block;
width: 400px;
height: 400px;
top: 20px;
background-color: rgb(0, 0, 0);
border-radius: 50%;
box-shadow: 0px 0px 10px 10px black;
}
#start_container button {
}
/*Game Container Styles*/
#game_container {
position: relative;
display: inline-block;
width: 400px;
height: 400px;
top: 20px;
background-color: rgb(0, 0, 0);
border-radius: 50%;
box-shadow: 0px 0px 10px 10px black;
}
.second_level{
transform: rotateY(180deg);
}
.third_level{
transform: rotateX(180deg);
}
/*Score Container*/
#score_container {
display: inline-block;
position: relative;
height: 150px;
width: 150px;
background-color: rgb(0, 0, 0);
top: -40px;
margin-left: -5px;
margin-right: 30px;
border-radius: 50%;
box-shadow: 0px 0px 10px 10px black;
}
#score_container #score {
display: inline-block;
height: 30px;
width: 80px;
color: #ffffff;
margin-left: 0;
margin-right: 0;
}
/*Level Container*/
#time_container {
display: inline-block;
position: relative;
height: 150px;
width: 150px;
background-color: rgb(0, 0, 0);
top: -40px;
margin-left: 30px;
border-radius: 50%;
box-shadow: 0px 0px 10px 10px black;
}
#time_container #time {
display: inline-block;
height: 30px;
width: 80px;
color: #ffffff;
margin-left: 0;
margin-right: 0;
}
/*Random Show Color Style*/
#show_color{
margin-top: 50px;
font-size: 40px;
font-family: sans-serif;
font-weight: 800;
}
/*Random Colors Classes*/
.random_color0{
color: green;
}
.random_color1{
color: red;
}
.random_color2{
color: yellow;
}
.random_color3{
color: blue;
}
.random_color4{
color: orange;
}
.random_color5{
color: purple;
}
/*Buttons Container Styles*/
#game_container #buttons_container {
position: relative;
display: inline-block;
margin:0 auto;
margin-top: 120px;
border-top: 1px solid white;
padding-top: 30px;
}
/*Buttons Style*/
#buttons_container button {
height: 40px;
width: 150px;
font-size: 30px;
font-weight: 800;
border: none;
border-radius: 3px;
background-color: rgb(0, 0, 0);
margin: 3px;
}
#buttons_container button:focus{
outline: 0;
}
#buttons_container button:hover{
cursor: pointer;
}
/*Game Over Container*/
#game_over_container {
display: none;
position: relative;
width: 400px;
height: 400px;
top: 20px;
background-color: rgb(0, 0, 0);
border-radius: 50%;
box-shadow: 0px 0px 10px 10px black;
}
<div id="main_container">
<!-- <div id="start_container">
<button id="start_game">PLAY GAME</button>
</div> -->
<div id="score_container">
<h4>SCORE:</h4>
<div id="score">0</div>
</div>
<div id="game_container">
<div id="show_color_container">
<div id="show_color"></div>
</div>
<div id="buttons_container">
<button class="btn_select" id="btn1">ONE</button>
<button class="btn_select" id="btn2">TWO</button>
<button class="btn_select" id="btn3">NEXT</button>
</div>
</div>
<div id="game_over_container">
<h2 id="game_over">GAME OVER</h2>
</div>
</div>
Inside openTheGame() you're using setInterval which calls startGame() every 3 seconds, which in turn creates (adds) new event handlers every 3 seconds, which call your console.logs etc. Replace setInterval with setTimeout:
function openTheGame(){
setTimeout(startGame, 3000);
};
openTheGame();
EDIT: did not thoroughly check your code, but if you need that function called every 3 seconds, then you need to move the setup of click handlers outside that function.

Categories

Resources