I am completeing the Etch-a-Sketch project of TheOdinProject. I want to access the grid's cell for changing it's color, but they are created in the scope of a for()
loop and that for()
loop is inside the scope of a function. I've searched other questions and not getting what I want or maybe I cannot understand whatis being conveyed.
The function for creating grid
function changeGridSize(number) {
let container = document.getElementById(`container`);
totalNumber = number * number;
while (container.hasChildNodes()) {
container.removeChild(container.firstChild);
}
for (let i = 0; i < totalNumber; i++) {
let gridSquare = document.createElement("div");
gridSquare.classList.add("grid_square");
let cellwidth = container.clientWidth / number + `px`;
let cellheight = container.clientHeight / number + `px`;
gridSquare.setAttribute(
`style`,
`width: ${cellwidth}; height: ${cellheight};`
);
container.appendChild(gridSquare);
}
}
The code for changing color
let color = document.getElementById(`colour_picker`);
color.addEventListener(`change`, changeColor() );
let choosenColour = color.value;
function changeColor() {
while (container.hasChildNodes()) {
gridSquare.setAttribute(`style`, `background-color: ${choosenColour};`)
}
}
When the user picks a color from the color picker the background color for the cells should change to that color which the user selected.
But when I add the change
event listener to the color picker the page is crashing and also when I try to change the grid size above 40x40.
Edit: html
<div id="outer_container">
<div id="container"> </div>
</div>
<div id="controls">
<input type="color" class="user_input" name="" id="colour_picker" value="#000000">
<div class="slider">
<div class="toggle_change" id="arrow_down"></div>
<input style="margin-bottom: 0;" class="user_input" type="range" min="2" max="100" value="16" name="options"
id="grid_range">
<div class="toggle_change" id="arrow_up"></div>
</div>
</div>
</body>```
There's one main problem in your code, being how you pass the callback function to the addEventListener
by invoking it instead of using its value.
Said that, I just simplified how you style the elements programmatically by using directly the style
property of the element instead of changing the value of the style
attribute.
I also decided to style the html that you didn't share according to my taste and most importatly setting the #container
as a flexbox to accomodate the n*n
squares inside.
let container = document.getElementById(`container`);
//on page loaded, click the #resetGrid button
document.addEventListener('DOMContentLoaded', ()=>{
document.getElementById('resetGrid').click();
})
//on click over the #resetGrid button, changeGridSize() accordingly
document.getElementById('resetGrid')
.addEventListener('click', (event)=>{
const size = document.getElementById('gridsize').value;
changeGridSize(size);
});
//empty the #container and add a number of div.grid_square based on arg number
function changeGridSize(number) {
totalNumber = number * number;
while (container.hasChildNodes()) {
container.removeChild(container.firstChild);
}
for (let i = 0; i < totalNumber; i++) {
let gridSquare = document.createElement("div");
gridSquare.classList.add("grid_square");
let cellwidth = container.clientWidth / number;
let cellheight = container.clientHeight / number;
gridSquare.style.width = `${cellwidth}px`;
gridSquare.style.height = `${cellheight}px`;
container.appendChild(gridSquare);
}
}
let color = document.getElementById(`colour_picker`);
color.addEventListener(`change`, changeColor);
//called when #color_picker change event triggers,
//setting the background of each single .grid_square accordingly
function changeColor(event) {
for (let box of container.children) {
box.style.background = this.value;
}
}
body {
display: flex;
justify-content: space-around;
align-items: center;
padding-top: 3em;
}
#container {
width: 100px;
height: 100px;
border: solid 1px black;
display: flex;
flex-wrap: wrap;
}
.grid_square {
border: solid 1px;
box-sizing: border-box;
}
/*controls styles*/
.controls label[for="color_picker"]{
vertical-align: text-bottom;
}
.controls .input-group {
display: flex;
align-items: center;
}
.controls #gridsize{
width: 2em;
margin-right: .5em;
}
.controls button{
width: 100%;
cursor: pointer;
}
<body>
<div id="container"></div>
<div class="controls">
<label for="colour_picker">Pick a color:</label>
<input id="colour_picker" type="color">
<br><br>
<div class="input-group">
<input id="gridsize" type="number" value="4" style="width: 50px;">
<button id="resetGrid">Reset</button>
</div>
</div>
</body>