How to activate mouseover on click/mousedown? - javascript

I am working on the etch-a-sketch project with The Odin Project and there's one thing I can't figure out. In the original project the grid elements will start to change colors once I hover over them but what I want to do is to only start the hovering function after I press the left mouse button.
Here is a working example of what I want to achieve.
const container = document.getElementById('container');
const reset = document.getElementById('reset');
const eraser = document.querySelector('#eraser');
const pencil = document.querySelector('#pencil');
const rainbow = document.querySelector('#rainbow');
const pickColor = document.querySelector('#color');
const shading = document.querySelector('#shading')
const gridSize = document.querySelector('#range');
let gridValue = document.querySelector('.grid-size');
let mode = '';
gridValue.textContent = `50x50`; // display default size of the grid
// create grid
function createGrid(size) {
size = gridSize.value;
container.style.gridTemplateColumns = `repeat(${size}, 1fr)`;
container.style.gridTemplateRows = `repeat(${size}, 1fr)`;
for (let i = 0; i < size * size; i++) {
const grid = document.createElement('div');
grid.setAttribute('id', 'grid');
container.appendChild(grid);
grid.addEventListener('mouseover', changeColor);
}
}
createGrid();
// change grid size depending on the user's choice
gridSize.addEventListener('input', function (e) {
let currentSize = e.target.value;
gridValue.textContent = `${currentSize}x${currentSize}`;
resetGrid();
});
// change color
function changeColor(e) {
if (mode === 'pencil') {
e.target.classList.add('black');
e.target.classList.remove('white');
e.target.style.backgroundColor = null;
e.target.style.opacity = null;
} else if (mode === 'rainbow') {
const green = Math.floor(Math.random() * 250);
const blue = Math.floor(Math.random() * 250);
const red = Math.floor(Math.random() * 250);
e.target.style.backgroundColor = `rgb(${red}, ${green}, ${blue})`;
e.target.style.opacity = null;
} else if (mode === 'erase') {
e.target.classList.add('white');
e.target.style.backgroundColor = null;
e.target.style.opacity = null;
} else if (mode === 'pickColor') {
e.target.style.backgroundColor = pickColor.value;
e.target.style.opacity = null;
} else if (mode === 'shading') {
e.target.classList.remove('white');
e.target.classList.add('black');
e.target.style.opacity = Number(e.target.style.opacity) + 0.2;
} else {
e.target.classList.add('black')
}
}
// reset grid
reset.addEventListener('click', () => resetGrid());
function resetGrid() {
container.innerHTML = '';
createGrid();
}
// erase
eraser.addEventListener('click', () => eraseMode());
function eraseMode() {
mode = 'erase';
}
// pencil
pencil.addEventListener('click', () => pencilMode());
function pencilMode() {
mode = 'pencil';
}
// rainbow
rainbow.addEventListener('click', () => rainbowMode());
function rainbowMode() {
mode = 'rainbow';
}
// pick a color
pickColor.addEventListener('click', () => pickColorMode());
function pickColorMode() {
mode = 'pickColor';
}
// shading
shading.addEventListener('click', () => shadeMode());
function shadeMode() {
mode = 'shading';
}
#import url('https://fonts.googleapis.com/css2?family=Inconsolata:wght#700;800&display=swap');
body {
text-align: center;
background-color: #4d56bd;
font-family: 'Inconsolata', monospace;
color: white;
}
h1 {
font-weight: 800;
font-size: 40px;
text-shadow: 3px 3px #1d1b1e;
color: #f4ce45
}
#container {
width: 600px;
height: 600px;
border: 3px solid #1d1b1e;
display: grid;
margin: 20px auto;
background-color: white;
box-shadow: 5px 5px #303030;
}
#grid {
border: none;
}
.black {
background-color: black;
}
.white {
background-color: white;
}
.button {
font-family: inherit;
padding: 10px;
font-size: 1em;
background-color: #303030;
box-shadow: 2px 2px #1d1b1e;
color: white;
margin: 0 5px;
}
#reset {
background-color: #f4ce45;
color: black;
}
.button:hover,
#reset:hover {
cursor: pointer;
background-color: #e7455a;
}
.ownColor {
margin: 10px;
}
.pickColor:hover {
cursor: auto;
background-color: #303030;
}
#color {
cursor: pointer;
}
.slider {
-webkit-appearance: none;
width: 30%;
height: 10px;
border-radius: 5px;
background: #1d1b1e;
margin: 10px;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 20px;
height: 20px;
border-radius: 50%;
background: #f4ce45;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 20px;
height: 20px;
border-radius: 50%;
background: #f4ce45;
cursor: pointer;
}
.grid-size {
font-size: 1.5rem;
margin-top: 20px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
<title>Etch-a-Sketch</title>
</head>
<body>
<h1>ETCH A SKETCH</h1>
<button id="reset" class="button">Reset</button>
<button id="pencil" class="button">Pencil</button>
<button id="eraser" class="button">Eraser</button>
<button id="rainbow" class="button">Rainbow</button>
<button id="shading" class="button">Shading</button>
<div class="ownColor">
<button class="button pickColor">Choose your own color:
<input type="color" id="color"></button>
</div>
<div class="grid-size"></div>
<input type="range" id="range" min="5" max="100" class="slider">
<div id="container"></div>
</body>
<script src="script.js"></script>
</html>

Well basically you can achieve this with a variable isMouseDown.
let isMouseDown;
document.addEventListener('mousedown', () => isMouseDown = true);
document.addEventListener('mouseup', () => isMouseDown = false);
then, use it where you need, for example:
// change color
function changeColor(e) {
if(!isMouseDown) return;
// ... rest of the code
}

Related

JavaScript: stop a function when another one is active

I am working on a sketchpad and basically I would like to allow the user to switch between hover-draw (hovering over divs will change their color, it's the default mode) and click-draw (you have to actually click the divs to color them).
I added a button which change the value of clickOn/hoverOn and I want the functions to work only if their associated variables are "on".
However when I click the button and hoverOn value becomes false, the hover function still executes and the divs get colored anyway.
Can anyone point me in the right direction?
EDIT: full code:
const container = document.querySelector('.container');
const newSize = document.querySelector('#grid-resize');
const clearBtn = document.querySelector('#clear');
const resetBtn = document.querySelector('#reset');
const randomBtn = document.querySelector('#random-color');
const modeBtn = document.querySelector('#change-mode');
const eraser = document.querySelector('#eraser');
let size = 16;
let hoverOn = true;
let clickOn = false;
let color = '#72A0C1';
newSize.addEventListener('input', changeSize);
clearBtn.addEventListener('click', clearGrid);
resetBtn.addEventListener('click', resetGrid);
modeBtn.addEventListener('click', changeMode);
randomBtn.addEventListener('click', drawRainbow);
eraser.addEventListener('click', () => {
if (color == 'white') {
color = '#72A0C1';
eraser.style.border = 'none';
} else {
color = 'white';
eraser.style.border = '2px dotted #FFC0CB';
}
});
let isMousedown = false;
container.addEventListener('mousedown', ()=>{isMousedown = true;});
container.addEventListener('mouseup', ()=>{isMousedown = false;});
function changeSize() {
const cells = document.querySelectorAll('.cell');
cells.forEach(cell => {
cell.remove();
});
size = newSize.value;
generateDiv(size);
}
function clearGrid() {
const cells = document.querySelectorAll('.cell');
cells.forEach(cell => {
cell.style.backgroundColor = 'white';
});
}
function resetGrid() {
const cells = document.querySelectorAll('.cell');
cells.forEach(cell => {
cell.remove();
});
size = 16;
newSize.value = size;
generateDiv();
}
function changeMode() {
if (hoverOn) {
hoverOn = false;
clickOn = true;
} else if (clickOn) {
clickOn = false;
hoverOn = true;
}
console.log (hoverOn, clickOn)
}
function setHoverMode() {
if (hoverOn == true) {
container.addEventListener('mouseover', function (e) {
e.target.style.background = `${color}`;
});
}
}
function setClickMode() {
if (clickOn == true) {
container.addEventListener('mousemove', (e) => {
if (isMousedown) {
e.target.style.backgroundColor = `${color}`;
}
});
container.addEventListener('mousemove', e => e.preventDefault());
}
}
function generateColor() {
let randomColor = '#';
let characters = 'ABCDEF0123456789';
for(let i=0; i < 6; i++) {
randomColor += characters.charAt(Math.floor(Math.random() * characters.length));
color = randomColor;
}
}
function drawRainbow() {
container.addEventListener('mousemove', ()=>{
generateColor();
});
}
function generateDiv() {
container.style.gridTemplateColumns = `repeat(${size}, 1fr)`;
container.style.gridTemplateRows = `repeat(${size}, 1fr)`;
for (let i = 0; i < size * size; i++) {
let cell = document.createElement('div');
cell.classList.add('cell');
container.appendChild(cell);
}
}
generateDiv(size);
html, body {
margin: 0;
padding: 20px;
width: 100%;
height: 100%;
box-sizing: border-box;
text-align: center;
}
h1 {
margin-top: 0;
}
.content {
display: flex;
justify-content: center;
gap: 5em;
}
.content .settings {
display: flex;
flex-direction: column;
width: 15%;
}
.content .grid-resize {
text-align: start;
margin-bottom: 2em;
}
.content .buttons {
display: flex;
flex-wrap: wrap;
gap: 1.5em;
}
.content .buttons button {
border: none;
box-shadow: 1px 1px rgba(128, 128, 128, 0.41);
border-radius: 15px;
width: 70px;
height: 70px;
}
.content .buttons button:hover {
box-shadow: 2px 2px #176fae;
background-color: #72A0C1;
color: white;
transform: scale(1.2);
}
.content .buttons button:active {
box-shadow: none;
background-color: #72A0C1;
color: white;
transform: scale(1);
}
.content .buttons button .eraser-border {
border: 1px solid black;
}
.container {
display: grid;
width: 400px;
height: 400px;
}
.container .cell {
background-color: white;
border: 1px solid rgba(220, 220, 220, 0.3);
}
<body>
<div class="main">
<h1>Draw something nice!</h1>
<div class="content">
<div class="settings">
<div class="grid-resize">
<label for="grid-resize">Change the grid size:</label>
<input type="range" id="grid-resize" min="4" max="100">
</div>
<div class="buttons">
<button id="clear" class="settings-buttons" title="Click here to clear the board">Clear All</button>
<button id="reset" class="settings=buttons" title="Click here to go back to original settings - this will clear the board">Reset</button>
<button id="change-mode" class="settings-buttons" title="Click here to change the mode">Draw Mode</button>
<button id="random-color" class="settings-buttons">Random Color</button>
<button id="black-shades" class="settings-buttons">Black Shades</button>
<button id="eraser" class="settings-buttons"><img src="images/rubber.svg">Eraser</button>
</div>
</div>
<div class="container">
</div>
</div>
</div>
You were close, just move mouseover/mousemove listeners outside of setHoverMode/setClickMode functions and do your condition checks inside those event listeners like below
container.addEventListener("mouseover", function (e) {
if (hoverOn) {
e.target.style.background = `${color}`;
}
});
container.addEventListener("mousemove", (e) => {
if (clickOn && isMousedown) {
e.target.style.backgroundColor = `${color}`;
}
});

How to reload all kinds of functions and all HTML code in JavaScript to restart a game?

Clicking on the Home button at the end of this project brings it to the beginning, but no function is reset. Level buttons are not also being enabled anew. If I enable those level buttons by writing some extra code for enabling, then the number of buttons given for each level will be doubled after selecting the level. In other words, for the first time due to selecting the basic level, there were 4 options, But when I click on the last home button and then select the medium level to play the game from the beginning, it becomes 16 options instead of 8.
//VARIABLE DECLARATION PART
let frontpage = document.querySelector(".front-page");
let playbutton = document.querySelector(".play");
let levelpage = document.querySelector(".levelpg");
let startbtn = document.querySelector(".startbtn");
let maingame = document.querySelector(".maingame");
let easybtn = document.querySelector(".easy");
let mediumbtn = document.querySelector(".medium");
let hardbtn = document.querySelector(".hard");
let nextbtn = document.querySelector(".nextbtn");
let pagecount = document.querySelector('.gamepagecount');
let getnumberdiv = document.querySelector('.numberbtn').children;
let resultpg = document.querySelector('.resultpage');
let backhome = document.querySelector('.backhome');
let finalscore = document.querySelector('.score');
let resulttext = resultpg.children[1];
let changeimg = document.querySelector('.resultpage img');
// PLAYBUTTON CLICK
playbutton.addEventListener("click", () => {
frontpage.classList.add("hidden");
levelpage.classList.remove("hidden");
levelpage.classList.add("visibility");
});
//GAME START FUNCTION
function startGame(level) {
if (level == "easy") {
mediumbtn.disabled = true;
hardbtn.disabled = true;
easybtn.disabled = true;
easybtn.classList.add('levelcolor');
startbtn.addEventListener("click", () => {
pagecount.innerHTML = `1 of 10`;
nextbtn.disabled = true
levelChange(4);
gameInterfaceChange()
mainGame(10);
//NEXTBUTTON FUNCTION
nextbtn.addEventListener('click', () => {
enableBtn(4)
pageCount(10);
mainGame(10);
})
});
}
else if (level == "medium") {
mediumbtn.disabled = true;
hardbtn.disabled = true;
easybtn.disabled = true;
mediumbtn.classList.add('levelcolor');
startbtn.addEventListener("click", () => {
pagecount.innerHTML = `1 of 15`;
nextbtn.disabled = true
levelChange(8);
gameInterfaceChange();
maingame.style.top = "20%";
mainGame(20);
//NEXTBUTTON FUNCTION
nextbtn.addEventListener('click', () => {
enableBtn(8)
pageCount(15)
mainGame(20);
})
});
}
else if (level == "hard") {
mediumbtn.disabled = true;
hardbtn.disabled = true;
easybtn.disabled = true;
hardbtn.classList.add('levelcolor');
startbtn.addEventListener("click", () => {
pagecount.innerHTML = `1 of 20`;
nextbtn.disabled = true
levelChange(12);
gameInterfaceChange();
maingame.style.top = "12%";
mainGame(30);
//NEXTBUTTON FUNCTION
nextbtn.addEventListener('click', () => {
enableBtn(12)
pageCount(20)
mainGame(30);
})
});
}
}
//PAGE SLIDING FUNCTION
function gameInterfaceChange() {
levelpage.classList.remove("hidden");
levelpage.classList.add("hidden");
maingame.classList.remove("hidden");
maingame.style.top = "25%";
maingame.classList.add("visibility");
}
// FUNCTION OF RANDOM INPUTING NUMBER IN DIV
function mainGame(maxnum) {
let numboxlen = getnumberdiv.length;
let wrongnum = Math.floor(Math.random() * maxnum) + 1;
let getnumber = [];
//DUPLICATE RANDOM NUMBER CHECKING
for (let i = 0; i < numboxlen; i++) {
let check = getnumber.includes(wrongnum);
if (check === false) {
getnumber.push(wrongnum);
}
else {
while (check === true) {
wrongnum = Math.floor(Math.random() * maxnum) + 1;
check = getnumber.includes(wrongnum);
if (check === false) {
getnumber.push(wrongnum);
}
}
}
}
// NUMBER PUTTING IN InnerHtml
for (var j = 0; j < numboxlen; j++) {
if (getnumber[j] < 10) {
getnumberdiv[j].innerHTML = '0' + getnumber[j];
}
else {
getnumberdiv[j].innerHTML = getnumber[j];
}
}
}
// BUTTON ADDING ACCORDING TO THE LEVEL
function levelChange(divnum) {
for (let index = 0; index < divnum; index++) {
let newBtn = document.createElement('button');
let newbtnNode = document.createTextNode('');
newBtn.appendChild(newbtnNode);
let gamebtn = document.getElementById('numbrbtn');
gamebtn.appendChild(newBtn);
newBtn.setAttribute("onclick", `numberClick(${index},${divnum})`);
}
}
//RIGHT - WRONG CHECKING FUNTION
var right = 0;
var wrong = 0;
function numberClick(index, divnum) {
let rightnumberindex = Math.floor(Math.random() * divnum);
if (index == rightnumberindex) {
nextbtn.disabled = false
right++;
//RIGHT AND WRONG BACKGROUND ADDING AND BUTTON DISABLE
getnumberdiv[index].classList.add("rightans");
for (let i = 0; i < divnum; i++) {
getnumberdiv[i].disabled = true;
}
}
else {
nextbtn.disabled = false
wrong++;
//RIGHT AND WRONG BACKGROUND ADDING AND BUTTON DISABLE
getnumberdiv[rightnumberindex].classList.add("rightans");
getnumberdiv[index].classList.add("wrongans");
for (let i = 0; i < divnum; i++) {
getnumberdiv[i].disabled = true;
}
}
}
// BUTTON ENABLE ON NEXT BUTTION CLICK
function enableBtn(divnum) {
for (let i = 0; i < divnum; i++) {
nextbtn.disabled = true
getnumberdiv[i].disabled = false;
getnumberdiv[i].classList.remove("wrongans");
getnumberdiv[i].classList.remove("rightans");
}
}
//PAGE COUNTING ACCORDING TO THE LEVEL
let currentpg = 1;
function pageCount(levelPg) {
currentpg++;
if (currentpg <= levelPg) {
if (currentpg == levelPg) {
nextbtn.innerHTML = 'Result'
pagecount.innerHTML = `${currentpg} of ${levelPg}`;
}
else {
pagecount.innerHTML = `${currentpg} of ${levelPg}`;
}
}
else {
result();
}
}
//FINAL RESULT FUNTION
function result() {
maingame.classList.remove("visibility");
maingame.classList.add("hidden");
resultpg.classList.remove('hidden')
resultpg.classList.add('visibility')
if (right > wrong) {
changeimg.setAttribute('src', 'trophy.png')
resulttext.innerHTML = `You Win`;
finalscore.innerHTML = `Your Right Score is : ${right} out of ${right + wrong}`;
}
else if (right == wrong) {
changeimg.setAttribute('src', 'draw.png')
resulttext.innerHTML = `It's Draw`;
finalscore.innerHTML = `Your Right Score is : ${right} out of ${right + wrong}`;
}
else if (right < wrong) {
changeimg.setAttribute('src', 'lose.png')
resulttext.innerHTML = `You Lose`;
finalscore.innerHTML = `Your Right Score is : ${right} out of ${right + wrong}`;
}
}
//BACK TO THE HOME FUNCTION
backhome.addEventListener('click', () => {
frontpage.classList.add("visibility");
frontpage.classList.remove("hidden");
resultpg.classList.add('hidden')
resultpg.classList.remove('visibility')
// enable level button
mediumbtn.disabled = false;
hardbtn.disabled = false;
easybtn.disabled = false;
})
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
margin-top: 50px;
}
.guessing-game {
position: relative;
color: white;
text-align: center;
margin: auto;
width: 350px;
height: 600px;
border-radius: 25px;
padding: 50px 30px;
background: linear-gradient(to right, #bd3f32, #cb356b);
}
.guessing-game .front-page .front-img {
height: 160px;
text-align: center;
}
.guessing-game .front-page img {
max-height: 100%;
}
.guessing-game .front-page .front-text h1 {
margin-top: 50px;
font-size: 1.8em;
}
.guessing-game .front-page .front-text p {
margin-top: 10px;
font-size: 1em;
}
.guessing-game .front-page .front-text button,
.resultpage button ,
.levelpg .easy,
.levelpg .medium,
.levelpg .hard,
.maingame .nextbtn {
margin-top: 30px;
width: 100%;
color: white;
padding: 15px;
outline: 0;
border: 0;
border-radius: 50px;
font-size: 0.9em;
background-color: #d64d5d;
box-shadow: rgba(17, 17, 26, 0.1) 0px 1px 0px,
rgba(17, 17, 26, 0.144) 0px 8px 24px, rgba(17, 17, 26, 0.1) 0px 16px 48px;
}
.guessing-game .front-page .front-text button:hover,
.maingame .nextbtn:hover,
.resultpage button:hover {
transition: 0.5s;
background-color: #c22f40;
}
/* Level page */
.visiblepg {
position: absolute;
top: 12%;
width: 290px;
}
.levelpg h1 {
margin: 45px 0 40px 0;
font-weight: 600;
font-size: 2.4em;
border: 1px solid white;
}
.levelpg .easy,
.levelpg .medium,
.levelpg .hard {
display: block;
margin-top: 15px;
padding: 12px;
background: white;
font-size: 1em;
border-radius: 10px;
font-weight: 400;
color: #c22f40;
}
.startbtn {
background: transparent;
border: 0;
outline: 0;
}
.levelpg i {
color: white;
margin-top: 50px;
font-size: 70px;
border-radius: 50%;
border: 2px solid transparent;
}
.levelpg i:hover {
background-color: white;
border: 2px solid white;
color: #c22f40;
transition: 0.5s;
}
/* GAME PART */
.maingame .gamepagecount {
background-color: #d64d5d;
color: white;
padding: 4px;
border-radius: 6px;
font-size: 0.8em;
font-weight: 600;
}
.maingame .gametext {
margin-top: 15px;
font-size: 1.2em;
}
.maingame .numberbtn {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
.maingame .numberbtn button {
margin-top: 40px;
width: 50px;
height: 50px;
background-color: white;
display: flex;
align-content: space-around;
justify-content: center;
align-items: center;
flex-wrap: wrap;
flex: 1 0 21%;
margin-left: 10px;
border: 0;
outline: 0;
border-radius: 10px;
font-size: 1em;
color: #c22f40;
font-weight: 600;
}
.maingame .numberbtn button:nth-child(1),
.maingame .numberbtn button:nth-child(5),
.maingame .numberbtn button:nth-child(9) {
margin-left: 0;
}
.resultpage h1 {
margin: 0px 0 40px 0;
}
.resultpage img {
margin-top: 45px;
width: 50%;
}
/* PRE DEFINE CSS */
.visibility {
visibility: visiible;
opacity: 2s;
transition: 0.5s;
transform: translateX(0px);
}
.hidden {
visibility: hidden;
opacity: 0;
transition: 0.5s;
transform: translateX(-30px);
}
.levelcolor {
transition: 0.5s;
color: white !important;
background-color: #c22f40 !important;
}
.rightans {
background-color: #27ae60 !important;
color: white !important;
transition: 0.5s;
}
.wrongans {
background-color: #fd4631 !important;
color: white !important;
transition: 0.5s;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght#0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
rel="stylesheet" />
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css"
integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous" />
<title>Guessing Game</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="guessing-game">
<div class="front-page">
<div class="front-img">
<img src="./question.png" alt="" />
</div>
<div class="front-text">
<h1>Guessing Game</h1>
<p>
You just need to chose the right number from the option. If your
guess is right more than wrong , you will win otherwise you will
fail! Let's see how good your sixth sense is!!!
</p>
<button class="play">Let's play</button>
</div>
</div>
<div class="levelpg hidden visiblepg">
<h1>Game level</h1>
<button class="easy" onclick="startGame('easy')">Easy</button>
<button class="medium" onclick="startGame('medium')">Medium</button>
<button class="hard" onclick="startGame('hard')">Hard</button>
<button class="startbtn"><i class="fas fa-play-circle"></i></button>
</div>
<div class="maingame visiblepg hidden">
<p class="gamepagecount">1</p>
<p class="gametext">Guess the number you think is right</p>
<div class="numberbtn" id="numbrbtn"></div>
<button class="nextbtn">Next</button>
</div>
<div class="resultpage levelpg hidden visiblepg">
<img src="" alt="" />
<h1></h1>
<div class="score"></div>
<button class="backhome">Home</button>
</div>
</div>
<script src="./main.js"></script>
</body>
</html>
In short, as soon as I click on the home button, I want the game to start anew, all the functions will be reset anew, and the HTML will be reset anew also. I hope my problem is enough clear to understand.
I have solved the problem.
I just add a reload function to solve this problem.
backhome.addEventListener('click', () => {
frontpage.classList.add("visibility");
frontpage.classList.remove("hidden");
resultpg.classList.add('hidden')
resultpg.classList.remove('visibility')
//reload function
window.location.reload();
})

Function removes items from localStorage only if run manually

I'm looking for advice/tips on how to fix a function that is supposed to remove items from localStorage. I'm following a tutorial by John Smilga that I found on Youtube. Although I've modeled my code on his, apparently, I have missed something.
This function works perfectly well if I run it manually from the console and pass in the id of the item that I want to remove from localStorage.
function removeFromLocalStorage(id) {
console.log(id);
let storageItems = getLocalStorage();
console.log(storageItems);
storageItems = storageItems.filter(function(singleItem) {
if (singleItem.id !== id) {
return singleItem;
}
})
console.log(storageItems);
localStorage.setItem("list", JSON.stringify(storageItems));
}
However, when this function is triggered by the deleteItem() function, it refuses to remove the item from localStorage. It still works, there are a bunch of console.logs in it that track its execution, and I can check that it receives the correct item id as the argument, but for some reason it doesn't filter out the item that needs to be removed. I am completely lost and have no idea how to identify the problem. I can't debug it with console.logs as I usually do. I will be very grateful if you help me find the problem. Any advice will be appreciated.
In case the entire code is needed, please find it below.
const form = document.querySelector(".app__form");
const alert = document.querySelector(".app__alert");
const input = document.querySelector(".app__input");
const submitBtn = document.querySelector(".app__submit-btn");
const itemsContainer = document.querySelector(".app__items-container");
const itemsList = document.querySelector(".app__items-list");
const clearBtn = document.querySelector(".app__clear-btn");
let editElement;
let editFlag = false;
let editId = "";
form.addEventListener("submit", addItem);
clearBtn.addEventListener("click", clearItems);
function addItem(e) {
e.preventDefault();
const id = Math.floor(Math.random() * 9999999999);
if (input.value && !editFlag) {
const item = document.createElement("div");
item.classList.add("app__item");
const attr = document.createAttribute("data-id");
attr.value = id;
item.setAttributeNode(attr);
item.innerHTML = `<p class='app__item-text'>${input.value}</p>
<div class='app__item-btn-cont'>
<button class='app__item-btn app__item-btn--edit'>edit</button>
<button class='app__item-btn app__item-btn--delete'>delete</button>
</div>`
const editBtn = item.querySelector(".app__item-btn--edit");
const deleteBtn = item.querySelector(".app__item-btn--delete");
editBtn.addEventListener("click", editItem);
deleteBtn.addEventListener("click", deleteItem);
itemsList.appendChild(item);
displayAlert("item added", "success");
addToLocalStorage(id, input.value);
setBackToDefault();
itemsContainer.classList.add("app__items-container--visible");
} else if (input.value && editFlag) {
editElement.textContent = input.value;
// edit local storage
editLocalStorage(editId, input.value);
setBackToDefault();
displayAlert("item edited", "success");
} else {
displayAlert("empty field", "warning");
}
}
function setBackToDefault() {
input.value = "";
editFlag = false;
editId = "";
submitBtn.textContent = "Submit";
submitBtn.className = "app__submit-btn";
}
function displayAlert(text, action) {
alert.textContent = text;
alert.classList.add(`app__alert--${action}`);
setTimeout(function() {
alert.textContent = "";
alert.classList.remove(`app__alert--${action}`);
}, 700)
}
function clearItems() {
const items = document.querySelectorAll(".app__item");
if (items.length > 0) {
items.forEach(function(singleItem) {
itemsList.removeChild(singleItem);
})
itemsContainer.classList.remove("app__items-container--visible");
displayAlert("items cleared", "cleared");
setBackToDefault();
}
}
function editItem(e) {
const item = e.currentTarget.parentElement.parentElement;
editElement = e.currentTarget.parentElement.previousElementSibling;
editId = item.dataset.id;
editFlag = true;
input.value = editElement.textContent;
submitBtn.textContent = "Edit";
submitBtn.classList.add("app__submit-btn--edit");
input.focus();
}
function deleteItem(e) {
const item = e.currentTarget.parentElement.parentElement;
const itemId = item.dataset.id;
removeFromLocalStorage(itemId);
displayAlert("item removed", "cleared");
setBackToDefault();
itemsList.removeChild(item);
if (itemsList.children.length === 0) {
itemsContainer.classList.remove("app__items-container--visible");
}
}
function addToLocalStorage(id, value) {
const itemsObj = {id: id, value: input.value};
let storageItems = getLocalStorage();
storageItems.push(itemsObj);
localStorage.setItem("list", JSON.stringify(storageItems));
}
function removeFromLocalStorage(id) {
console.log(id);
let storageItems = getLocalStorage();
console.log(storageItems);
storageItems = storageItems.filter(function(singleItem) {
if (singleItem.id !== id) {
return singleItem;
}
})
console.log(storageItems);
localStorage.setItem("list", JSON.stringify(storageItems));
}
function editLocalStorage(id, value) {
}
function getLocalStorage() {
return localStorage.getItem("list") ? JSON.parse(localStorage.getItem("list")) : [];
}
* {
margin: 0;
padding: 0;
}
.app {
width: 70%;
max-width: 600px;
margin: 75px auto 0;
}
.app__title {
text-align: center;
/* color: #1B5D81; */
margin-top: 20px;
color: #377FB4;
}
.app__alert {
width: 60%;
margin: 0 auto;
text-align: center;
font-size: 20px;
color: #215884;
border-radius: 7px;
height: 23px;
transition: 0.4s;
text-transform: capitalize;
}
.app__alert--warning {
background-color: rgba(243, 117, 66, 0.2);
color: #006699;
}
.app__alert--success {
background-color: rgba(165, 237, 92, 0.4);
color: #3333ff;
}
.app__alert--cleared {
background-color: #a978da;
color: white;
}
.app__input-btn-cont {
display: flex;
margin-top: 30px;
}
.app__input {
width: 80%;
box-sizing: border-box;
font-size: 20px;
padding: 3px 0 3px 10px;
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
border-right: none;
border: 1px solid #67B5E2;
background-color: #EDF9FF;
}
.app__input:focus {
outline: transparent;
}
.app__submit-btn {
display: block;
width: 20%;
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
border-left: none;
background-color: #67B5E2;
border: 1px solid #67B5E2;
cursor: pointer;
font-size: 20px;
color: white;
transition: background-color 0.7s;
padding: 3px 0;
}
.app__submit-btn--edit {
background-color: #95CB5D;
}
.app__submit-btn:active {
width: 19.9%;
padding: 0 0;
}
.app__submit-btn:hover {
background-color: #377FB4;
}
.app__submit-btn--edit:hover {
background-color: #81AF51;
}
.app__items-container {
visibility: hidden;
/* transition: 0.7s; */
}
.app__items-container--visible {
visibility: visible;
}
.app__item {
display: flex;
justify-content: space-between;
margin: 20px 0;
}
.app__item:hover {
background-color: #b9e2fa;
border-radius: 10px;
}
.app__item-text {
padding-left: 10px;
font-size: 20px;
color: #1B5D81;
}
.app__item-btn-cont {
display: flex;
}
.app__item-btn-img {
width: 20px;
height: 20px;
}
.app__item-btn {
border: none;
background-color: transparent;
cursor: pointer;
display: block;
font-size: 18px;
}
.app__item-btn--edit {
margin-right: 45px;
color: #2c800f;
}
.app__item-btn--delete {
margin-right: 15px;
color: rgb(243, 117, 66);
}
.app__clear-btn {
display: block;
width: 150px;
margin: 20px auto;
border: none;
background-color: transparent;
font-size: 20px;
color: rgb(243, 117, 66);
letter-spacing: 2px;
cursor: pointer;
transition: border 0.3s;
border: 1px solid transparent;
}
.app__clear-btn:hover {
border: 1px solid rgb(243, 117, 66);
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" name="viewport" content="width=device-width,
initial-scale=1">
<link rel="stylesheet" href="list.css">
<title>To Do List App</title>
</head>
<body>
<section class="app">
<form class="app__form">
<p class="app__alert"></p>
<h2 class="app__title">To Do List</h2>
<div class="app__input-btn-cont">
<input class="app__input" type="text" id="todo" placeholder="do stuff">
<button class="app__submit-btn">Submit</button>
</div>
</form>
<div class="app__items-container">
<div class="app__items-list">
</div>
<button class="app__clear-btn">Clear Items</button>
</div>
</section>
<script src="list.js"></script>
</body>
</html>
Your code is fine you just used the wrong comparison operator.
In your case you are comparing 2 IDs (operands) to see if they match up, so you should use normal operators such as (==, !=), but instead in your case, you have used strict operators which are used to compare the operand type and the operand itself.
You can learn more about Comparison Operators here.
Ultimatly,
In your function removeFromLocalStorage(id), you have an extra equal sign in your if function.
Instead of:
if (singleItem.id !== id) {
return singleItem;}
It should be:
if (singleItem.id != id) {
return singleItem;}
Hope this helps.

How can I change inner.HTML when click on button multiple times

I am trying to change button text and style when clicking on button. Code is working when changing Generate to Reset button however it doesn't work from reset to generate. It seems that code is working just in first click. How can I fix this?
// Change Generate Button to Reset#
let generateBtn = document.getElementById("generateBtn");
generateBtn.addEventListener("click", () => {
if ((generateBtn.innerHTML = "GENERATE")) {
generateBtn.innerHTML = "RESET";
generateBtn.classList.add("resetBtn-shown");
} else {
generateBtn.innerHTML = "GENERATE";
generateBtn.classList.remove("resetBtn-shown");
}
});
.generateBtn-shown {
background-color: red;
color: #eba341;
font-size: 1.5rem;
font-weight: 500;
border-radius: 0.5rem;
width: 10rem;
height: 3rem;
border: none;
}
.resetBtn-shown {
background-color: #21b884;
color: white;
}
<button id="generateBtn" class="generateBtn-shown">GENERATE</button>
In if statements, you need to have == instead of equals. So in your case it needs to be:
if ((generateBtn.innerHTML == "GENERATE")) {
This article explains it pretty well.
// Change Generate Button to Reset#
let generateBtn = document.getElementById("generateBtn");
generateBtn.addEventListener("click", () => {
if ((generateBtn.innerHTML == "GENERATE")) {
generateBtn.innerHTML = "RESET";
generateBtn.classList.add("resetBtn-shown");
} else {
generateBtn.innerHTML = "GENERATE";
generateBtn.classList.remove("resetBtn-shown");
}
});
.generateBtn-shown {
background-color: red;
color: #eba341;
font-size: 1.5rem;
font-weight: 500;
border-radius: 0.5rem;
width: 10rem;
height: 3rem;
border: none;
}
.resetBtn-shown {
background-color: #21b884;
color: white;
}
<button id="generateBtn" class="generateBtn-shown">GENERATE</button>
// Change Generate Button to Reset#
let generateBtn = document.getElementById("generateBtn");
generateBtn.addEventListener("click", () => {
if ((generateBtn.innerHTML === "GENERATE")) { //=== instead of =
generateBtn.innerHTML = "RESET";
generateBtn.classList.add("resetBtn-shown");
} else {
generateBtn.innerHTML = "GENERATE";
generateBtn.classList.remove("resetBtn-shown");
}
});
.generateBtn-shown {
background-color: red;
color: #eba341;
font-size: 1.5rem;
font-weight: 500;
border-radius: 0.5rem;
width: 10rem;
height: 3rem;
border: none;
}
.resetBtn-shown {
background-color: #21b884;
color: white;
}
<button id="generateBtn" class="generateBtn-shown">GENERATE</button>
try this..
you should use textContent instead of innerHtml .. it will give you text from html tag .. use includes method to compare text ..
Search it on google : innertext vs innerhtml vs textcontent ..
let generateBtn = document.getElementById("generateBtn");
generateBtn.addEventListener("click", (e) => {
if (e.target.textContent.includes("GENERATE")) {
e.target.innerText = "RESET";
e.target.classList.add("resetBtn-shown");
} else {
e.target.innerText = "GENERATE";
e.target.classList.remove("resetBtn-shown");
}
});
.generateBtn-shown {
background-color: red;
color: #eba341;
font-size: 1.5rem;
font-weight: 500;
border-radius: 0.5rem;
width: 10rem;
height: 3rem;
border: none;
}
.resetBtn-shown {
background-color: #21b884;
color: white;
}
<button id="generateBtn" class="generateBtn-shown">GENERATE</button>

How to pass a parentNode.id as a parameter to an element out of the querySelector

I have these elements created inside a "querySelector('ul'). It's working property.
I want the "blue-Save" button to have the same function as the "yellow-Save".
But the Blue-save button was created in the HTML file, and the Yellow-Save button was created in JavaScript to listen to an event from the "querySelector('ul').
Is there anyway I can just link the Blue-Save to react as if I was clicking in the Yellow-Save?
(I'm sorry if I didn't explain it property or If it seems too confused, this is my first application, It doesn't seems too organized but I'm focused in making things work before dive in 'well developed apps').
Thank You Everyone!
var todoList = {
todos: [],
addTodo: function (todoText) {
this.todos.push({
todoText: todoText,
/*the name of the property (even if it is the same name as the parameter) never change. Only the value, which follows in this case is following the parameter*/
completed: false
});
},
changeTodo: function (position, todoText) {
this.todos[position].todoText = todoText;
},
deleteTodo: function (position) {
this.todos.splice(position, 1);
},
toggleCompleted: function (position) {
var todo = this.todos[position];
todo.completed = !todo.completed;
/*Here we flip the boolean to his oposite value. if todo.completed is equal false, so changes it to true, and so on. */
},
toggleAll: function () {
// recording the number of todos and completed todos
var totalTodos = this.todos.length;
var completedTodos = 0;
// get the number of completed todos.
this.todos.forEach(function (todo) {
if (todo.completed === true) {
completedTodos++;
}
});
this.todos.forEach(function (todo) {
// Case 1: If everything is true, make everything.
if (completedTodos === totalTodos) {
todo.completed = false;
// Case 2: Otherwise, make everything true.
} else {
todo.completed = true;
}
});
}
};
var handlers = {
addTodo: function () {
var addTodoTextInput = document.getElementById('add-todo-text-input');
todoList.addTodo(addTodoTextInput.value);
addTodoTextInput.value = '';
view.displayTodos();
},
changeTodo: function (position) {
var changeTodoTextInput = document.getElementById('change-todo-text-input');
todoList.changeTodo(position, changeTodoTextInput.value);
changeTodoTextInput.value = '';
view.displayTodos();
},
deleteTodo: function (position) {
todoList.deleteTodo(position);
view.displayTodos();
},
toggleCompleted: function (position) {
todoList.toggleCompleted(position);
view.displayTodos();
},
toggleAllButton: function () {
todoList.toggleAll();
view.displayTodos();
}
};
var view = {
displayTodos: function () {
var todosUl = document.querySelector('ul');
todosUl.innerHTML = '';
todoList.todos.forEach(function (todo, position) {
var todoLi = document.createElement('li');
var todoTextWithCompletion = '';
if (todo.completed === true) {
todoTextWithCompletion = todo.todoText;
todoLi.classList.add('item-completed');
} else {
todoTextWithCompletion = todo.todoText;
}
todoLi.id = position;
todoLi.textContent = todoTextWithCompletion;
todoLi.appendChild(this.createEditButton());
todoLi.appendChild(this.createToggleButton());
todoLi.appendChild(this.createDeleteButton());
todoLi.appendChild(this.createSaveButton());
todosUl.appendChild(todoLi);
}, this);
},
createDeleteButton: function () {
var deleteButton = document.createElement('button');
deleteButton.textContent = '\u2715';
deleteButton.className = 'delete-button';
return deleteButton;
},
createToggleButton: function () {
var toggleButton = document.createElement('button');
toggleButton.textContent = '\u2713';
toggleButton.className = 'toggle-button';
return toggleButton;
},
createSaveButton: function () {
var saveButton = document.createElement('button');
saveButton.textContent = 'Save';
saveButton.className = 'save-button';
return saveButton;
},
createEditButton: function () {
var editButton = document.createElement('button');
editButton.textContent = '\u270E';
editButton.className = 'edit-button';
return editButton;
},
setUpEventListeners: function () {
var todosUl = document.querySelector('ul');
todosUl.addEventListener('click', function (event) {
// Get the element that was clicked on.
var elementClicked = event.target;
// Check if elementClicked is a delete button.
if (elementClicked.className === 'delete-button') {
handlers.deleteTodo(parseInt(elementClicked.parentNode.id));
} else if (elementClicked.className === 'toggle-button') {
handlers.toggleCompleted(parseInt(elementClicked.parentNode.id));
} else if (elementClicked.className === 'save-button') {
handlers.changeTodo(parseInt(elementClicked.parentNode.id));
} else if (elementClicked.className === 'edit-button') {
}
});
}
};
view.setUpEventListeners();
body {
font-family: Helvetica, sans-serif;
font-size: 25px;
background: rgb(236, 236, 236);
}
h1 {
color: rgb(255, 255, 255);
text-align: center;
font-family: Helvetica, sans-serif;
font-size: 50px;
text-transform: uppercase;
background: rgb(48, 48, 48);
position: relative;
}
.container {
margin: auto;
width: 50%;
}
ul {
list-style: none;
padding:0px;
margin: 10px;
}
.add-button {
background-color: rgb(68, 165, 230); /* Blue */
border: none;
color: white;
margin:auto;
padding: 15px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
border-radius: 5px;
width:20%;
}
.add-button:hover {
background-color :rgb(53, 127, 177); /* Green */
color: white;
}
.save-change-button {
background-color: rgb(68, 165, 230); /* Blue */
border: none;
color: white;
margin:auto;
padding: 15px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
border-radius: 5px;
width:20%;
}
.save-change-button:hover {
background-color :rgb(53, 127, 177); /* Green */
color: white;
}
.toggle-all-button {
background-color: rgb(38, 156, 38); /* Green */
border: none;
color: white;
margin: 10px 0;
padding: 15px 32px;
text-align: center;
text-decoration: none;
font-size: 16px;
border-radius: 5px;
width: 100%;
}
.toggle-all-button:hover {
background-color : rgb(36, 114, 36); /* Green */
color: white;
}
.edit-button {
background-color: rgb(219, 208, 50); /* Green */
border: none;
color: white;
padding: 0;
text-align: center;
text-decoration: none;
font-size: 18px;
border-radius: 5px;
width: 25px;
height: 25px;
margin: 0 0 0 10px;
}
.edit-button:hover {
background-color: rgb(185, 175, 26); /* Green */
color: white;
}
.toggle-button {
background-color: rgb(38, 156, 38); /* Green */
border: none;
color: white;
padding: 0;
text-align: center;
text-decoration: none;
font-size: 18px;
border-radius: 5px;
width: 25px;
height: 25px;
margin: 0 0 0 10px;
}
.toggle-button:hover {
background-color: rgb(36, 114, 36); /* Green */
color: white;
}
.delete-button {
background-color: rgb(168, 44, 44); /* Green */
border: none;
color: white;
margin: 0 0 0 10px;
padding: 0;
text-align: center;
text-decoration: none;
font-size: 18px;
border-radius: 5px;
width: 25px;
height: 25px;
}
.delete-button:hover {
background-color :rgb(128, 31, 31); /* Green */
color: white;
}
.save-button {
background-color: rgb(219, 208, 50); /* Green */
border: none;
color: white;
padding: 0;
text-align: center;
text-decoration: none;
font-size: 18px;
border-radius: 5px;
width: 55px;
height: 25px;
margin: 0 10px;
}
.save-button:hover {
background-color :rgb(185, 175, 26); /* Green */
color: white;
}
.add-input {
margin: 10px 0;
padding: 6px 0;
text-align: center;
font-family: Arial, Helvetica, sans-serif;
font-size: 18px;
width: 78%;
}
.edit-input {
margin: 10px 0;
padding: 6px 0;
text-align: center;
font-family: Arial, Helvetica, sans-serif;
font-size: 18px;
width: 78%;
}
.item-completed {
text-decoration: line-through;
}
::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
color: rgba(209, 209, 209, 0.555);
font-family: 'Times New Roman', Times, serif;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Todo List</title>
<link href="index.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="container">
<h1>Todo List</h1>
<div>
<input id="add-todo-text-input" class="add-input" placeholder="Add a New Todo to Your List" type="text">
<button class="add-button" onclick="handlers.addTodo()">Add</button>
</div>
<ul>
</ul>
<div id="edit-todo"">
<input id="change-todo-text-input" class="edit-input" placeholder="Add the Changes Your Want to Make" type="text">
<button class="save-change-button">Save</button>
</div>
<div id="toggle-all"">
<button class="toggle-all-button" onclick="handlers.toggleAllButton()">Toggle All</button>
</div>
</div>
<script src="index.js"></script>
</body>
</html>
You can add a common class to both blue and yellow buttons, and attach a click event by the class name like below
$(".custom_save_button").on("click", function() {
//your code
});
Since you are creating that button, sharing the same class won't just work as expected, instead use delegated events which allow you to attach events on new elements added to the DOM
Add a common class for both and then add an event listener for that class using event delegation.
For this example Let's suppose you chose the class name: stack_class
//I added this function for you to be able to know if an element has a class
function hasClass( target, className ) {
return new RegExp('(\\s|^)' + className + '(\\s|$)').test(target.className);
}
//you could change body to the closest parent's selector both buttons share
document.querySelector('body').addEventListener('click', function(event) {
var clickedElement = event.target;
if(hasClass(clickedElement, "stack_class")) {
//create your functionality for both buttons here
}
});
If you assign a common class to both buttons, then you can add the same event listener to all buttons that have that class. Here is a simple example:
var saveButton = document.createElement('button');
saveButton.textContent = 'Save';
saveButton.className = 'save-button yellow-button';
body = document.querySelector('body');
body.appendChild(saveButton);
buttons = document.getElementsByClassName('save-button');
for (var i = 0; i < buttons.length; i += 1) {
buttons[i].addEventListener('click', function (event) {
alert('Hello!');
});
}
.yellow-button {
background: #ffff00;
}
.blue-button {
background: #0000ff;
}
<button class="save-button blue-button">Save</button>

Categories

Resources