Setting strict grid size in CSS grid - javascript

I am currently trying to complete an etch-a-sketch project but am having issues with setting a grid to respect a strict size value. I want to set it so that the grid squares become smaller and the overall container remains the same however what I currently have forces the grid to go off the page.
I have tried max-height and max-width settings but these don't seem to do anything. Could someone please help me ?
Javascript Code
const button16 = document.querySelector('.smol');
const button24 = document.querySelector('.med');
const button64 = document.querySelector('.large');
const button = document.querySelector('.reset');
const container = document.querySelector('.container');
function row(num, columns){
for (let i = 0; i < num; i++){
const div = document.createElement('div')
container.appendChild(div);
for (let i = 0; i < columns; i++){
const div2 = document.createElement('div2', );
div.appendChild(div2);
}
}
}
hover(row(16, 16))
button16.addEventListener('click', () => {
clearGrid();
hover(row(16, 16))
});
button24.addEventListener('click', () => {
clearGrid();
hover(row(24, 24))
});
button64.addEventListener('click', () => {
clearGrid();
hover(row(64, 64))
});
function hover() {
const wrapper2 = container.querySelectorAll('div2');
wrapper2.forEach(wrapper2 => wrapper2.addEventListener('mouseenter', () => {
const hash = '#';
let randomColor = Math.floor(Math.random()*16777215).toString(16);
wrapper2.style.backgroundColor = hash + randomColor;
}));
wrapper2.forEach(wrapper2 => button.addEventListener("click", () => {
wrapper2.style.backgroundColor = 'white';
}));
}
function clearGrid() {
container.innerHTML = null
}
My CSS
.container {
display: grid;
grid-template-columns:repeat(64, 1fr);
width: 500px;
height: 500px;
}
div2 {
border: solid 0.1px;
color: #424242;
display: grid;
width:30px;
height: 25px;
box-sizing: border-box
}
.buttonbox {
display: flex;
width: 500px;
}
.reset, .smol, .med, .large {
padding: 5px;
}
My html
<!DOCTYPE HTML>
<html lan="en">
<head>
<meta charset = utf-8>
<link rel= 'stylesheet' href="Styles.css" ></script>
<script src = GameLogic.js defer></script>
<title>My Etch-A-Sketch Project</title>
</head>
<body>
<h1>Etch-A-Sketch</h1>
<div class = "container">
</div>
<div class = 'buttonbox'>
<button class="reset">
Clear Grid
</button>
<button class="smol">
16 x 16
</button>
<button class="med">
24 x 24
</button>
<button class="large">
64 x 64
</button>
</div>
</body>
</html>

Related

trying to show re render the page when i click on the show details button

Hello guys i am new to this i am trying to re render my page any time i click on the show details buttons so i can show the name, height and gender of the sky wars characters i have tried initializing a variable to false and on click i tried changing the value to true but it did not work. please here is my code.
const containerEl = document.getElementById("container");
const list = document.createDocumentFragment();
const images = [
"https://oyster.ignimgs.com/mediawiki/apis.ign.com/star-wars-episode-7/2/2d/Luke.jpg?width=1280",
"https://images.immediate.co.uk/production/volatile/sites/3/2019/10/EP9-FF-001686-336e75b.jpg?quality=90&resize=980,654",
"https://hips.hearstapps.com/digitalspyuk.cdnds.net/17/07/1487160686-r2-d2.jpg",
"https://lumiere-a.akamaihd.net/v1/images/darth-vader-main_4560aff7.jpeg?region=0%2C67%2C1280%2C720",
"https://www.costumerealm.com/wp-content/uploads/2019/12/51G4Jox9MlL._SX466_.jpg",
"https://static.wikia.nocookie.net/starwars/images/e/eb/OwenCardTrader.png/revision/latest?cb=20171108050140",
"https://static.wikia.nocookie.net/fanmade-works/images/8/8d/Beru_Lars.png/revision/latest/scale-to-width/360?cb=20200317025929",
"https://static.wikia.nocookie.net/star-wars-canon-extended/images/2/23/R5.jpg/revision/latest?cb=20160123232521",
"https://static.wikia.nocookie.net/starwars/images/0/00/BiggsHS-ANH.png/revision/latest?cb=20130305010406",
"https://media.gq.com/photos/622919842677fb88bf480855/16:9/w_2143,h_1205,c_limit/Screen%20Shot%202022-03-09%20at%204.15.50%20PM.png"
]
const getData = async () => {
const res = await fetch("https://swapi.dev/api/people");
const resData = await res.json();
const result = resData.results;
console.log(result)
main(result)
}
getData();
const main = (data) => {
let isVisible = false;
containerEl.innerHTML = "";
data.map(({ gender, height, name }, i) => {
const starWars = `
<img class="images" src=${images[i]}/>
<button id="btn" class="btn">Show Details</button>
<h1 class="starwars">${isVisible ? name : ""}</h1>
<h3>${isVisible ? gender : ""}</h3>
<h3>${isVisible ? height : ""}</h3>
`;
const item = document.createElement("div");
item.classList.add("items")
item.innerHTML = starWars
const btn = item.querySelector(".btn");
btn.addEventListener("click", () => {
isVisible = true
})
list.appendChild(item)
})
containerEl.append(list)
}
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./style/index.css" >
<title>Star Wars</title>
</head>
<body>
<!-- Write your implementation here -->
<div id="container" class="container">
</div>
<script src="./script/index.js"></script>
</body>
</html>
This approach is not possible. The string literals, such as ${isVisible ? name : ""} are evaluated at the time that your template item is created, so since you've set the isVisible is false, it will only ever produce an empty string.
Instead, generate your string template with the values and then use a class to toggle the visibility of the details.
const containerEl = document.getElementById("container");
const images = [
"https://oyster.ignimgs.com/mediawiki/apis.ign.com/star-wars-episode-7/2/2d/Luke.jpg?width=1280",
"https://images.immediate.co.uk/production/volatile/sites/3/2019/10/EP9-FF-001686-336e75b.jpg?quality=90&resize=980,654",
"https://hips.hearstapps.com/digitalspyuk.cdnds.net/17/07/1487160686-r2-d2.jpg",
"https://lumiere-a.akamaihd.net/v1/images/darth-vader-main_4560aff7.jpeg?region=0%2C67%2C1280%2C720",
"https://www.costumerealm.com/wp-content/uploads/2019/12/51G4Jox9MlL._SX466_.jpg",
"https://static.wikia.nocookie.net/starwars/images/e/eb/OwenCardTrader.png/revision/latest?cb=20171108050140",
"https://static.wikia.nocookie.net/fanmade-works/images/8/8d/Beru_Lars.png/revision/latest/scale-to-width/360?cb=20200317025929",
"https://static.wikia.nocookie.net/star-wars-canon-extended/images/2/23/R5.jpg/revision/latest?cb=20160123232521",
"https://static.wikia.nocookie.net/starwars/images/0/00/BiggsHS-ANH.png/revision/latest?cb=20130305010406",
"https://media.gq.com/photos/622919842677fb88bf480855/16:9/w_2143,h_1205,c_limit/Screen%20Shot%202022-03-09%20at%204.15.50%20PM.png"
]
async function getData () {
const res = await fetch("https://swapi.dev/api/people");
const resData = await res.json();
return resData.results;
}
async function main () {
const data = await getData();
containerEl.innerHTML = "";
const list = document.createElement("ul")
data.map(({ gender, height, name }, i) => {
const starWars = `
<img class="images" src=${images[i]}/>
<button id="btn" class="btn">Show Details</button>
<div class="details">
<h2 class="starwars">${name}</h2>
<h3>${gender}</h3>
<h3>${height}</h3>
</div>
`;
const item = document.createElement("li");
item.classList.add("item", "hidden")
item.innerHTML = starWars
const btn = item.querySelector(".btn");
btn.addEventListener("click", toggleVisibility)
list.appendChild(item)
})
containerEl.append(list)
}
main()
function toggleVisibility(event) {
const el = event.target.closest('.item')
el.classList.toggle("hidden")
}
img {
width: 100%;
}
ul {
padding: 0;
margin: 0;
list-style-type: none;
display: grid;
gap: 1rem;
}
li {
border: 2px solid #ccc;
border-radius: .5rem;
overflow: hidden;
}
button {
font-weight: bold;
border: 0;
background-color: #222;
padding: .5rem .75rem;
color: white;
}
.item {
display: grid;
width: 25rem;
margin: auto;
}
.details {
padding: 1rem;
}
.hidden .details {
display: none;
}
<div id="container" class="container"></div>

Weird bug occurring for Event listeners( I think)

Whenever I click either 'Reset', 'Color Black', or 'Erase' randomly the entire grid will color in black. If that happens and I click Erase I can clear them off and then sometimes randomly the excess black that was randomly created will disappear. Not really sure what the issue is. I THINK it may be an issue with how the Event Listeners are set up, but this is the only configuration of them that gets the buttons to work. Any ideas what the issue might be?
let blackBtn = document.querySelector('#black');
let eraseBtn = document.querySelector('#eraser');
let resetBtn = document.querySelector('#reset');
let resize = document.querySelector('.resize');
let value = 16; // For default 16x16 grid size
//Create grid
function createGrid(size = value) {
grid.style["grid-template-rows"] = `repeat(${size}, 1fr)`;
grid.style["grid-template-columns"] = `repeat(${size}, 1fr)`;
for (let i = 0; i < size * size; i++) {
const block = document.createElement('div');
block.className = 'block';
grid.appendChild(block);
}
grid.addEventListener("mouseover", colorBlack);
resize.addEventListener("click", resizeGrid);
resetBtn.addEventListener("click", clearGrid);
eraseBtn.addEventListener("click", eraseColor);
blackBtn.addEventListener("click", blackPaint);
}
//Resize the grid
function resizeGrid() {
const newSize = parseInt(prompt("New Size: ", 16));
grid.innerHTML = '';
resize.removeEventListener("click", resizeGrid);
grid.removeEventListener("mouseover", colorBlack);
createGrid(newSize);
}
//Fill in background color of black
function colorBlack(e) {
if (e.target.className !== "block") return false;
e.target.style.backgroundColor = 'black';
}
//Clear background color from grid
function clearGrid(size, newSize) {
grid.innerHTML = '';
resize.removeEventListener("click", resizeGrid);
grid.removeEventListener("mouseover", colorBlack);
createGrid();
}
//Colors divs black after clicking 'Color Black'
function blackPaint(e) {
grid.removeEventListener("mouseover", eraseColor);
grid.addEventListener("mouseover", (e) => {
e.target.style.backgroundColor = 'black';
})
}
//Colors over black divs with white to 'erase' it
function eraseColor(e) {
grid.removeEventListener("mouseover", colorBlack);
grid.addEventListener("mouseover", (e) => {
e.target.style.backgroundColor = 'white';
})
}
createGrid();
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
#grid {
width: 20rem;
height: 20rem;
border: 1px solid #333;
display: grid;
flex-wrap: grid;
}
.block {
border: 1px solid black;
}
<!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">
<title>Etch-A-Sketch</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<p>Etch-A-Sketch</p>
</header>
<div class="gameBoard">
<div id="actions">
<button class="resize">Resize</button>
<button id="reset">Reset</button>
<button id="black">Color Black</button>
<button id="eraser">Eraser</button>
</div>
<div id='grid'></div>
<div class="block"></div>
</div>
<script src="script.js"></script>
</body>
</html>
When you click on Black or Erase, you add event listeners that call anonymous functions. These can't be removed with removeEventListener() when you switch modes. So these old event listeners continue to run, erasing and filling in elements.
You should have two functions, colorBlack() and colorWhite(), and switch between them in the mouseover event listener. Also, when you reset or resize, you should go back to black.
The problem with Clear is that it calls createGrid(), which adds all the event listeners again. You remove some of the old listeners before you call it, but not all, so you get duplication. You should separate creating the grid and adding the event listeners, so you don't repeat the listeners, and then you wouldn't need to remove them.
let blackBtn = document.querySelector('#black');
let eraseBtn = document.querySelector('#eraser');
let resetBtn = document.querySelector('#reset');
let resize = document.querySelector('.resize');
let value = 16; // For default 16x16 grid size
//Create grid
function createGrid(size = value) {
grid.style["grid-template-rows"] = `repeat(${size}, 1fr)`;
grid.style["grid-template-columns"] = `repeat(${size}, 1fr)`;
for (let i = 0; i < size * size; i++) {
const block = document.createElement('div');
block.className = 'block';
grid.appendChild(block);
}
}
function addListeners() {
grid.addEventListener("mouseover", colorBlack);
resize.addEventListener("click", resizeGrid);
resetBtn.addEventListener("click", clearGrid);
eraseBtn.addEventListener("click", eraseColor);
blackBtn.addEventListener("click", blackPaint);
}
//Resize the grid
function resizeGrid() {
const newSize = parseInt(prompt("New Size: ", 16));
grid.innerHTML = '';
createGrid(newSize);
blackPaint();
}
//Fill in background color of black
function colorBlack(e) {
if (e.target.className !== "block") return false;
e.target.style.backgroundColor = 'black';
}
//Fill in background color of white
function colorWhite(e) {
if (e.target.className !== "block") return false;
e.target.style.backgroundColor = 'white';
}
//Clear background color from grid
function clearGrid(size, newSize) {
grid.innerHTML = '';
createGrid();
blackPaint();
}
//Colors divs black after clicking 'Color Black'
function blackPaint(e) {
grid.removeEventListener("mouseover", colorWhite);
grid.addEventListener("mouseover", colorBlack);
}
//Colors over black divs with white to 'erase' it
function eraseColor(e) {
grid.removeEventListener("mouseover", colorBlack);
grid.addEventListener("mouseover", colorWhite);
}
createGrid();
addListeners();
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
#grid {
width: 20rem;
height: 20rem;
border: 1px solid #333;
display: grid;
flex-wrap: grid;
}
.block {
border: 1px solid black;
}
<!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">
<title>Etch-A-Sketch</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<p>Etch-A-Sketch</p>
</header>
<div class="gameBoard">
<div id="actions">
<button class="resize">Resize</button>
<button id="reset">Reset</button>
<button id="black">Color Black</button>
<button id="eraser">Eraser</button>
</div>
<div id='grid'></div>
<div class="block"></div>
</div>
<script src="script.js"></script>
</body>
</html>

Unable to place an image using Javascript for a random image generator code

[image of a mole to be placed randomly in the squares created][1
**
I am trying to code the game called 'Whack-a-mole'. I created h1 and div elements to be placed on screen using javascript . Then I wanted to place an image inside the squares to appear randomly, but it does not appear in the squares. Could you please help me with where I went wrong ?
Thank You
. I add
// MY CODE
// const h1 = document.createElement('h1');
// h1.textContent = 'Your Score: ';
// h1.id = 'score';
// document.body.append(h1);
// const time = document.createElement('h1');
// time.textContent = 'Time Left: ';
// time.id = 'time';
// document.body.append(time);
// const grid = document.createElement('div');
// grid.className = 'grid';
// document.body.append(grid);
// for (let i = 0; i < 8; i++) {
// let square = document.createElement('img');
// square.className = 'square';
// square.id = ('data-id', i+1);
// grid.append(square);
// };
// const result = document.querySelector('#score');
// const left = document.querySelector('#time');
// const boxes = document.querySelectorAll('.square');
// const images = document.querySelector('.mole');
// function randomMole() {
// boxes.forEach(box => {
// box.classList.remove('images');
// });
// let randomSquare = boxes[Math.floor(Math.random() * 8)];
// randomSquare.classList.add('images');
// };
// randomMole();
// Ania code
const squares = document.querySelectorAll('.square')
const mole = document.querySelector('.mole')
const timeLeft = document.querySelector('#time-left')
const score = document.querySelector('#score')
let result = 0
let hitPosition
let currentTime = 60
let timerId = null
function randomSquare() {
squares.forEach(square => {
square.classList.remove('mole')
})
let randomSquare = squares[Math.floor(Math.random() * 9)]
randomSquare.classList.add('mole')
hitPosition = randomSquare.id
}
randomSquare();
squares.forEach(square => {
square.addEventListener('mousedown', () => {
if (square.id == hitPosition) {
result++
score.textContent = result
hitPosition = null
}
})
})
function moveMole() {
timerId = setInterval(randomSquare, 500)
}
moveMole()
function countDown() {
currentTime--
timeLeft.textContent = currentTime
if (currentTime == 0) {
clearInterval(countDownTimerId)
clearInterval(timerId)
alert('GAME OVER! Your final score is ' + result)
}
}
let countDownTimerId = setInterval(countDown, 1000)
.grid {
width: 600px;
height: 300px;
display: flex;
flex-wrap: wrap;
}
.square {
width: 135px;
height: 135px;
border: solid rgb(11, 8, 8) 1px;
}
.mole {
background-image: url('images/mole.jpg');
background-size: cover;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="style.css" rel="stylesheet">
</head>
<body>
<h2>Your score:</h2>
<h2 id="score">0</h2>
<h2>Time Left:</h2>
<h2 id="time-left">60</h2>
<div class="grid">
<div class="square" id="1"></div>
<div class="square" id="2"></div>
<div class="square" id="3"></div>
<div class="square" id="4"></div>
<div class="square" id="5"></div>
<div class="square" id="6"></div>
<div class="square" id="7"></div>
<div class="square" id="8"></div>
<div class="square" id="9"></div>
</div>
<script src="Ania JS/Ania game 3.js"></script>
</body>
</html>
**
I suppose you need the .mole class to display the image. Here's a a minimal reproducable example for your code.
Play with it by forking this stackblitz project.
Or play the game itself 🙃
document.addEventListener(`click`, evt =>
evt.target.id === `redo` && randomMole());
document.body.insertAdjacentHTML(
`beforeend`, `<div class="grid">${
[...Array(8)].map((_, i) => `<img class="square" data-id=${i}>`)
.join(``) }</div>`);
document.querySelector(`#redo`).click();
function randomMole() {
const mole = document.querySelector(`.mole`);
mole && mole.classList.remove('mole');
document.querySelectorAll('.square')[Math.floor(Math.random() * 8)]
.classList.add(`mole`);
};
.grid {
width: 600px;
height: 300px;
display: flex;
flex-wrap: wrap;
}
.square {
width: 64px;
height: 64px;
border: solid rgb(11, 8, 8) 1px;
margin-right: 2px;
}
.mole {
background-image: url('//cdn.pixabay.com/photo/2012/05/02/17/24/ground-45742_960_720.png');
background-size: cover;
}
<p><button id="redo">random mole position</button></p>

how to reset color grid?

I am creating a simple etch-a-sketch game. currently on hover it colors in black. I am trying to use a button to reset the colors back to white. However, i can't get the button to function with an event listener, if i add an alert it displays the alert but nothing else. Please guide me and supply a documentation that I can reference as I want to learn and fixing it without explaining will be counterproductive at this point.
Thank you !
const containerGrid = document.getElementById("mainGrid");
function makeGrid(col) {
for (let i = 0; i < col * col; i++) {
const gridAdd = document.createElement("div");
gridAdd.classList.add("box");
gridAdd.textContent = "";
containerGrid.appendChild(gridAdd);
}
}
makeGrid(16); // make grid 16*16
const btnClear = document.getElementById("clear");
//mouseover event black - need to link to button (well done :)
const boxes = document.querySelectorAll('.box').forEach(item => {
item.addEventListener('mouseover', event => {
item.style.backgroundColor = "black";
})
});
btnClear.addEventListener("click", () => {
boxes.style.backgroundColor = "white";
});
const changeGrid = document.getElementById(".sizechange");
/*clearBtn.forEach.addEventListener("click", function () {
clearBtn.style.color ="white";
});
*/
/*const randomBtn = document.getElementById("randomgen").addEventListener('click',(e) => {
console.log(this.classname)
console.log(e.currentTarget === this)
}) */
//change color
#mainGrid {
display: grid;
justify-content: center;
align-items: center;
grid-template-columns: repeat(16, 1fr);
grid-template-rows: auto;
margin-left: 150px;
width: 200px;
}
.box {
color: black;
border: 3px solid;
height: 10px;
width: 10px;
}
<!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">
<title>Etch-a-Sketch</title>
<link type="text/css" rel="stylesheet" href="styles.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<div id="colorContainer">
<input type="radio" id="blackchoice" value="color" name="black" class="defaultbtn">
<label for="defaultcolor">black</label>
<input type="radio" id="randomgen" class="hey">
<label for="randomchoice">random</label>
</div>
<div id="changeGrid">
<button id="clear">clear</button>
</div>
<div id="mainGrid"></div>
<script src="app.js"></script>
</body>
</html>
A couple of related problems:
The variable boxes is undefined. It looks as though it was required to be the set elements with class box. When it is being defined this is indeed done, but then made undefined by the forEach attached to it. Separate out these two things and boxes will become the collection of all elements with class box.
Then when the clear is clicked you need to step through each of these boxes making their background color white, so again use a forEach.
<!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">
<title>Etch-a-Sketch</title>
<link type="text/css" rel="stylesheet" href="styles.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
#mainGrid {
display: grid;
justify-content: center;
align-items: center;
grid-template-columns: repeat(16, 1fr);
grid-template-rows: auto;
margin-left: 150px;
width: 200px;
}
.box {
color: black;
border: 3px solid;
height: 10px;
width: 10px;
}
</style>
</head>
<body>
<div id="colorContainer">
<input type="radio" id="blackchoice" value="color" name="black" class="defaultbtn">
<label for="defaultcolor">black</label>
<input type="radio" id="randomgen" class="hey">
<label for="randomchoice">random</label>
</div>
<div id="changeGrid">
<button id="clear">clear</button>
</div>
<div id="mainGrid"></div>
<script src="app.js"></script>
<script>
const containerGrid = document.getElementById("mainGrid");
function makeGrid(col) {
for (let i = 0; i < col * col; i++) {
const gridAdd = document.createElement("div");
gridAdd.classList.add("box");
gridAdd.textContent = "";
containerGrid.appendChild(gridAdd);
}
}
makeGrid(16); // make grid 16*16
const btnClear = document.getElementById("clear");
//mouseover event black - need to link to button (well done :)
const boxes = document.querySelectorAll('.box');
boxes.forEach(box => {
box.addEventListener('mouseover', event => {
box.style.backgroundColor = "black";
})
});
btnClear.addEventListener("click", () => {
boxes.forEach(box => {
box.style.backgroundColor = "white";
});
});
const changeGrid = document.getElementById(".sizechange");
/*clearBtn.forEach.addEventListener("click", function () {
clearBtn.style.color ="white";
});
*/
/*const randomBtn = document.getElementById("randomgen").addEventListener('click',(e) => {
console.log(this.classname)
console.log(e.currentTarget === this)
}) */
//change color
</script>
</body>
</html>
Simplify your CSS
Use a SELECT element for your colors
Define the gridTemplateColumns in JS, not in CSS.
Use simpler functions
Use global variables to store the current grid size and color
Don't forget to clear your grid before changing the size
Assign the mouseenter Event on each cell on creation!
Add a boolean variable isPenDown for a better user experience!
const NewEL = (sel, prop) => Object.assign(document.createElement(sel), prop);
const EL_grid = document.querySelector("#grid");
const EL_clear = document.querySelector("#clear");
const EL_color = document.querySelector("[name=color]");
const EL_size = document.querySelector("[name=size]");
let size = parseInt(EL_size.value, 10);
let color = "black";
let isPenDown = false;
function makeGrid() {
EL_grid.innerHTML = ""; // Clear current grid!
for (let i = 0; i < size ** 2; i++) {
EL_grid.style.gridTemplateColumns = `repeat(${size}, 1fr)`;
EL_grid.append(NewEL("div", {
className: "box",
onmousedown() { isPenDown = true; paint(this); },
onmouseup() { isPenDown = false; },
onmouseenter() { if (isPenDown) paint(this); },
}));
}
};
function paint(EL) {
EL.style.backgroundColor = color;
}
EL_clear.addEventListener("click", () => {
const tmp_color = color; // Remember current color
color = "transparent"; // Temporarily set it to transparent
EL_grid.querySelectorAll(".box").forEach(paint); // Paint all cells as transparent
color = tmp_color; //* Reset as it was before.
});
EL_color.addEventListener("change", () => {
color = EL_color.value;
if (color === "random") color = `hsl(${~~(Math.random() * 360)}, 80%, 50%)`;
});
EL_size.addEventListener("change", () => {
size = parseInt(EL_size.value, 10);
makeGrid();
});
// INIT!
makeGrid();
#grid {
display: inline-grid;
margin: 10px 0;
}
#grid .box {
border: 1px solid;
height: 10px;
width: 10px;
margin: 0;
user-select: none;
}
<div>
<label>
Size:
<input type="number" name="size" value="16">
</label>
<label>
Color:
<select name="color">
<option value="black">black</option>
<option value="white">white</option>
<option value="red">red</option>
<option value="yellow">yellow</option>
<option value="orange">orange</option>
<option value="fuchsia">fuchsia</option>
<option value="transparent">CLEAR (transparent)</option>
<option value="random">RANDOM COLOR</option>
</select>
</label>
<button id="clear">Clear canvas</button>
</div>
<div id="grid"></div>

refactoring javascript code to create for loop

I am practicing Javascript. I want each link to display something different in the DOM when clicked.
Here is my current Javascript that works.
//used a 'for' loop to hide each 'notes' page
const element = document.querySelectorAll(".notes");
for (let x = 0; x < element.length; x++)
element[x].style.display = 'none';
const html_link= document.getElementById('html-link');
const css_link = document.getElementById('css-link');
const javascript_link = document.getElementById('js-link');
const html_notes = document.getElementById('html-notes');
const css_notes = document.getElementById('css-notes');
const js_notes = document.getElementById('js-notes');
html_link.onclick = function() {
html_notes.style.display = "block";
css_notes.style.display = "none";
js_notes.style.display = "none";
}
css_link.onclick = function() {
css_notes.style.display = "block";
html_notes.style.display = "none";
js_notes.style.display = "none";
}
javascript_link.onclick = () => {
js_notes.style.display = "block";
html_notes.style.display = "none";
css_notes.style.display = "none";
}
How can I refactor it using a for loop? My thinking was for each link clicked, display notes. But I am struggling to figure out how to display the notes div correctly that matches the link clicked. This is what I have started.
const links = document.querySelectorAll('.links')
for (const link of links) {
link.addEventListener('click', function() {
let ref = event.target.parentElement.id.replace('link','notes');
//replaces parent element with id 'notes'
const show = document.getElementById(ref);
//'show' div with new id
})
}
Welcome, fellow newbie! I've taken the liberty of writing the html and very minimal styling as well. This is my first attempt at an answer on stackoverflow.
Please note some features of the code I've added:
'links' class added to all links.
'notes' class added to all notes.
'data-notes' attribute added to all links (with the id of each link's respective notes)
<!DOCTYPE html>
<html dir="ltr" lang="en-US">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0"/>
</head>
<body>
<div class="outer">
<div id="html-link" data-notes="html-notes" class="links">
<p>html-link</p>
</div>
<div id="css-link" data-notes="css-notes" class="links">
<p>css-link</p>
</div>
<div id="javascript-link" data-notes="javascript-notes" class="links">
<p>javascript-link</p>
</div>
</div>
<div class="outer">
<div id="html-notes" class="notes">
<p>html-notes</p>
</div>
<div id="css-notes" class="notes">
<p>css-notes</p>
</div>
<div id="javascript-notes" class="notes">
<p>javascript-notes</p>
</div>
</div>
<style>
.links {
cursor: pointer;
background: green;
color: white;
padding: 1rem;
margin: 1rem;
}
.notes {
display: none;
background: blue;
color: white;
padding: 1rem;
margin: 1rem;
}
.outer {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
margin: 2rem 0;
}
</style>
<script>
const links = document.querySelectorAll('.links');
const notes = document.querySelectorAll('.notes');
for (const link of links) {
link.onclick = function () {
for (const note of notes) {
if (note.id == link.dataset.notes) {
note.style.display = "block";
} else {
note.style.display = "none";
}
}
}
}
</script>
</body>
</html>

Categories