I'm doing a project to make an etch-a-sketch every time I hover on the grid. What I'm trying to do is to make a button to clear up all the colors made.
The sketch picture.
I guess what I need to do is to remove the style elements while clicking the button. But I'm just note sure how to link the button with the style elements.
const container = document.querySelector(".container");
// const table = document.createElement('div');
// table.classList.add('grid-square');
// table.textContent = 'hello';
// container.appendChild(table);
function makeTable(rows, cols) {
container.style.setProperty('--grid-rows', rows);
container.style.setProperty('--grid-cols', cols);
for (i = 0; i < (rows * cols); i++){
const cell = document.createElement('div');
// cell.innerText = (i + 1);
container.appendChild(cell).className = "table";
};
};
makeTable(16, 16);
// const container = document.querySelector('.container')
const grids = document.querySelectorAll('.table')
grids.forEach(element => {
element.addEventListener('mouseover', (e) => {
e.target.style.backgroundColor = randomColor();
console.log(e)
})
});
function randomColor() {
var generateColor = '#' + Math.floor(Math.random()*16777215).toString(16);
return generateColor;
}
function resizeGrid() {
sketchSize = prompt("Enter 1 to 100 to resize sketch");
return sketchSize;
}
// const button = document.querySelector('button')
// button.addEventListener('click', (e) => {
// });
:root {
--grid-rows: 1;
--grid-cols: 1;
}
.container {
display: grid;
/* grid-gap: 1em; */
grid-template-rows: repeat(var(--grid-rows), 1fr);
grid-template-columns: repeat(var(--grid-cols), 1fr);
/* border: 1px solid black; */
width: 50%;
size: 960px;
}
.table {
padding: 1em;
border: 1px solid coral;
text-align: center;
/* border: none; */
}
header {
display: flex;
justify-content: center;
margin: 20px;
gap: 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>
<script src="index.js" defer></script>
<link rel="stylesheet" href="index.css">
</head>
<body>
<header>
<button class="clear-button">Clear</button>
<button class="resize">Resize</button>
</header>
<div class="container"></div>
</body>
</html>
Cheers!!
To answer my own question, I figured how to do it.
const clear = document.querySelector('.clear-button')
clear.addEventListener('click', () => {
grids.forEach(element => {
element.style.backgroundColor = null;
})
})
I was struggling earlier because I'm not sure how to put other elements (e.g. grids) to the new eventListener.
Related
I'm making a grid and I'm not sure how to make the cells fill the space between them when the grid size changes.
I have a function that generates a grid and receives size as a parameter.
What should be added to the grid-square class to make the cells fill the entire space?
//get the grid div
const container = document.querySelector("#container");
function changeColor(e) {
const hoverColor = Math.floor(Math.random() * 16777215).toString(16);
e.target.style.backgroundColor = "#" + hoverColor;
}
function createDivs(size) {
//generate grid elements
for (let i = 0; i < size * size; i++) {
const newDiv = document.createElement("div");
newDiv.classList.add("grid-square");
newDiv.addEventListener("mouseover", changeColor);
container.appendChild(newDiv);
}
}
createDivs(2);
* {
box-sizing: border-box;
}
#container {
display: flex;
background-color: rgba(49, 49, 49, 0.281);
width: 50vw;
height: 50vh;
flex-wrap: wrap;
}
.grid-square {
background-color: white;
width: 50%;
aspect-ratio: 1/1;
}
.grid-square:hover {
cursor: pointer;
}
<!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 Sketck</title>
<link rel="stylesheet" href="style.css" />
<script src="script.js" defer></script>
</head>
<body>
<div id="container"></div>
</body>
</html>
So this is the way I did it. I changed from flex box to grid. Grid has a property called grid-template-columns that defines how many columns you have and how wide each one is. The syntax here is grid-template-columns: repeat(n, 1fr) where n is the number of columns you want.
In order to set the column numbers in javascript, I've used a css custom property (also called a css variable) to define the column numbers. To set the custom property itself I've set the element's style attribute to define that property on load.
Have a look below:
//get the grid div
const container = document.querySelector("#container");
function changeColor(e) {
const hoverColor = Math.floor(Math.random() * 16777215).toString(16);
e.target.style.backgroundColor = "#" + hoverColor;
}
function createDivs(size) {
//generate grid elements
for (let i = 0; i < size * size; i++) {
const newDiv = document.createElement("div");
newDiv.classList.add("grid-square");
newDiv.addEventListener("mouseover", changeColor);
container.appendChild(newDiv);
}
// Added this
container.style.cssText="--cols: "+size;
}
createDivs(5);
* {
box-sizing: border-box;
}
#container {
/* added this */
display: grid;
grid-template-columns: repeat(var(--cols), 1fr);
/* end of added css */
background-color: rgba(49, 49, 49, 0.281);
width: 50vw;
height: 50vh;
flex-wrap: wrap;
}
.grid-square {
background-color: white;
aspect-ratio: 1/1;
}
.grid-square:hover {
cursor: pointer;
}
<div id="container"></div>
The solution was to set the width when creating the cells.
//get the grid div
const container = document.querySelector("#container");
function changeColor(e) {
const hoverColor = Math.floor(Math.random() * 16777215).toString(16);
e.target.style.backgroundColor = "#" + hoverColor;
}
function createDivs(size) {
//generate grid elements
for (let i = 0; i < size * size; i++) {
const newDiv = document.createElement("div");
newDiv.classList.add("grid-square");
newDiv.addEventListener("mouseover", changeColor);
//Setting the width
newDiv.style.width = 100 / size + "%";
container.appendChild(newDiv);
}
}
createDivs(6);
* {
box-sizing: border-box;
}
#container {
display: flex;
background-color: rgba(49, 49, 49, 0.281);
width: 50vw;
height: 50vh;
flex-wrap: wrap;
}
.grid-square {
background-color: white;
width: 50%;
aspect-ratio: 1/1;
}
.grid-square:hover {
cursor: pointer;
}
<!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 Sketck</title>
<link rel="stylesheet" href="style.css" />
<script src="script.js" defer></script>
</head>
<body>
<div id="container"></div>
</body>
</html>
I'm working on an Etch A Sketch app for The Odin Project and I want to adjust one of the requirements where all I need to do is move the mouse on screen as a continuous stroke where each pixel touched on mouseover is filled, which is what's happening right now with my code.
What I want to change is the mouseover on my tile EventListener where it's really a continuous stroke on mousedown. I did try changing the e.target command in the setTiles function to toggle after changing the tile.addEventListener to mousedown, but it only works on each press of the left mouse button.
I'm trying to figure out a way to make this continuous on mousedown instead of using mouseover. I've included the code I have so far in the question.
const container = document.querySelector('#container');
const grid = document.querySelector('#grid');
const userInput = document.querySelector('#user-input');
let penDown = false;
grid.style.fontSize = '1em';
// Set pixel width and height
let wdt = '1em';
let hgt = '1em';
// Ask the user for the number of tiles for the sketch grid
function getUserInput() {
let input = parseInt(prompt(`Please enter the grid size you'd like`));
input <= 100 || !isNaN(input)
? createSketchGrid(input)
: alert('Please enter a valid number less than or equal to 100.');
}
// Event listener to create tiles in mouseover
function setTiles(e) {
e.target.classList.add('fill');
}
// function deleteTiles(e) {
// e.target.classList.toggle('fill');
// }
container.addEventListener('mousedown', function () {
penDown = true;
});
container.addEventListener('mouseup', function () {
penDown = false;
});
// Create the grid
function createSketchGrid(tiles) {
let gridSize = tiles * tiles;
for (let i = 0; i < gridSize; i++) {
let tile = document.createElement('div');
tile.style.width = wdt;
tile.style.height = hgt;
grid.appendChild(tile);
// tile.addEventListener('mouseover', setTiles, false);
if ((penDown === true)) {
tile.addEventListener('mousemove', setTiles);
}
}
}
userInput.addEventListener('click', getUserInput);
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 10px;
}
h1 {
font-size: 3rem;
}
.grid {
/* font-size: 1.6rem; */
display: flex;
flex-wrap: wrap;
gap: 0.1em;
border: 2px solid black;
background-color: lightgrey;
flex: 0 0 32em;
}
.fill {
flex-wrap: wrap;
background-color: 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" type="text/css" href="styles/style.css">
<script type="text/javascript" src="js/main.js" defer></script>
</head>
<body>
<h1 class="title">Etch A Sketch</h1>
<div id="container" class="container">
<button id="user-input" class="btn user-input" value="Grid Size">Grid Size</button>
<div id="grid" class="grid">
</div>
</div>
</body>
</html>
im trying to make static grid with a button that can change number of boxes in it (from 16x16 to 64x64 and anything between). Grid is 40rem x 40rem, when i try to change manually number of boxes in makeGrid() function it works fine up to 20 (boxes change size accordingly), but anything above 20 stays the same size and gets cutoff from my grid. If there is no grid css overflow property stated, grid width change depending on number of boxes but boxes themself won't shrink
my code:
size button is not working yet, grid size need to be changed mannualy in makeGrid function
const grid = document.getElementById('grid');
const size = document.getElementById('size');
const eraser = document.getElementById('eraser');
const color = document.getElementById('color');
const gridBorder = document.getElementById('grid-borders');
const clear = document.getElementById('clear');
// grid
function makeGrid(number) {
number = number || 16;
let cellWidth = 40 / number + 'rem';
let cellHeight = 40 / number + 'rem';
grid.style.gridTemplateColumns = `repeat( ${number}, 1fr)`;
grid.style.gridTemplateRows = `repeat(${number}, 1fr)`;
for (let i = 0; i < number * number; i++) {
let cell = document.createElement('div');
grid.appendChild(cell).id = 'box';
cell.classList.add('border');
cell.classList.add('box');
cell.style.backgroundColor = 'white';
cell.style.width = cellWidth;
cell.style.height = cellHeight;
}
size.textContent = `${number} x ${number}`;
}
makeGrid();
// drawing on hover
color.addEventListener('click', function () {
grid.addEventListener('mouseover', function (e) {
e.target !== grid ? (e.target.style.backgroundColor = 'black') : null;
});
});
function changeColor(event) {
event.target.style.backgroundColor = 'black';
}
// erase functionality
eraser.addEventListener('click', function () {
grid.addEventListener('mouseover', function (e) {
e.target !== grid ? (e.target.style.backgroundColor = 'white') : null;
});
});
// grid borders
const allBoxes = document.querySelectorAll('.box');
gridBorder.addEventListener('click', function () {
allBoxes.forEach((box) => {
box.classList.toggle('no-border');
box.classList.toggle('border');
});
});
// clear button
clear.addEventListener('click', function () {
allBoxes.forEach((box) => {
box.style.backgroundColor = 'white';
});
});
// size button
// size.addEventListener('click', function () {
// let number = prompt(`Enter grid size less or equal to 100`);
// if (number !== Number.isInteger()) {
// return;
// } else if (number > 100) {
// number = prompt(`Enter grid size greater or equal to 100`);
// }
// });
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
height: 100vh;
background-color: aquamarine;
}
#grid {
display: grid;
justify-content: center;
border: 1px solid #ccc;
width: 40rem;
height: 40rem;
min-width: 0;
min-height: 0;
overflow: hidden;
}
.box {
padding: 1em;
}
#title {
display: flex;
align-items: flex-end;
justify-content: center;
height: 180px;
}
#container {
display: flex;
height: 60%;
width: 1259px;
align-items: flex-start;
justify-content: flex-end;
gap: 20px;
padding-top: 20px;
}
#menu {
display: flex;
flex-direction: column;
gap: 10px;
}
.border {
outline: 1px solid black;
}
.no-border {
outline: none;
}
.black-bg {
background: black;
}
.white-bg {
background: white;
}
<!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" />
<script src="script.js" defer></script>
</head>
<body>
<div id="title">
<h1>Etch-a-Sketch</h1>
</div>
<main id="container">
<div id="menu">
<button id="size"></button>
<button id="color">Color</button>
<button id="eraser">Eraser</button>
<button id="clear">Clear</button>
<button id="grid-borders">Grid Borders</button>
</div>
<div id="grid"></div>
</main>
</body>
</html>
"Why won't my grid cells go below 32px?" - have you checked your padding (hint: 32px is exactly equal to 2 * 16px which in turn is exactly equal to your padding of 1em with most browsers implementing a default font-size of 16px). –
David Thomas
box padding was set to 1em which caused my problem, after deleting it my grid worked as intended
Although I have no errors and the code seems fine the game etc a sketch does not even appear when I open in browser he index1 html, I double checked whether the connection with my js file is the issue. Why it does not appear in browser?
HTML
<!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="stylesheet" href="styles1.css">
<title>Etch-a-sketch game</title>
</head>
<body>
<div id="buttonDIV"></div>
<div id="container"></div>
</body>
<script src="main1.js" defer></script>
</html>
CSS
:root {
--grid-cols: 1;
--grid-rows: 1;
}
#container {
display: grid;
grid-template-rows: repeat(var(--grid-rows), 1fr);
grid-template-columns: repeat(var(--grid-cols), 1fr);
}
.grid-item {
padding: 1em;
border: 1px solid #ddd;
text-align: center;
}
JavaScript
const container = document.getElementById("container");
function makeGrid(rows, cols) {
while(document.querySelector("button") !== null) {
document.querySelector("button").remove();
}
container.style.setProperty('--grid-rows', rows);
container.style.setProperty('--grid-cols', cols);
container.style.width = "960px";
container.style.overflow = "hidden";
// console.log(container);
// console.log(rows);
// console.log(cols);
for (c = 0; c < (rows * cols); c++) {
let cell = document.createElement("div");
cell.style.minHeight ="0";
cell.style.minWidth = "0";
cell.style.overflow = "hidden";
container.appendChild(cell).className = "grid-item";
cell.addEventListener("mouseover",()=> {
cell.style.backgroundColor = "black";
})// makes thins black
createButton();
};
function createButton() {
const butonDiv = document.querySelector("#buttonDIV");
const resetButton = document.createElement("button");
resetButton.textContent = "reset grid!";
resetButton.style.margin = "20px";
butonDiv.appendChild(resetButton);
resetButton.addEventListener('click',()=>{
document.querySelectorAll(".grid-item".forEach(e => {e.remove()}))
let userGridinput = prompt("Please enter the number of grid squares(Max 100)");
if(userGridinput > 100){
alert("ERROR!Your grid size cannot be bigger han 100!");
return
};
rows = userGridinput;
cols = userGridinput;
makeGrid(rows,cols);
});
};
}
please help me as I have gowned frustrated with this,
Kind of a JavaScript noob here. I'm using DOM manipulation for a project and need to make it so that the grid items in my container change color after being hovered on. Why won't my hoverColor() function do anything? I assume that it is a problem with my "grid-item" class not working right.
I haven't adjusted the container sizing options yet, just trying to make the event listener work first.
//query selectors
const container = document.querySelector('#container');
//Function that creates GRID
function addDivs(rows, cols){
container.style.setProperty('--grid-rows', rows);
container.style.setProperty('--grid-cols', cols);
for (i = 0; i < (rows * cols); i++){
let square = document.createElement("div");
square.classList.add('grid-item');
container.appendChild(square);
}
hoverColor();
}
//function that creates a random color
let randomColor = function() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
//function that changes div color uponed being hovered
function hoverColor() {
let item = document.querySelector('.grid-item');
item.addEventListener('mouseover', () => {
item.style.backgroundColor = `${randomColor()}`;
});
}
//grid creationg
addDivs(16, 16);
:root {
--grid-cols: 1;
--grid-rows: 1;
}
#container {
display: grid;
grid-gap: 0.5em;
grid-template-rows: repeat(var(--grid-rows), 1fr);
grid-template-columns: repeat(var(--grid-cols), 1fr);
border: 3px solid black;
padding: 1em;
}
#container:hover {
box-shadow: 0 5px 5px rgba(0,0,0,0.19), 0 5px 5px rgba(0,0,0,0.23);
}
.grid-item {
padding: 1em;
border: 1px solid #ddd;
text-align: center;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="container"></div>
<script src="script.js"></script>
</body>
</html>
There were two problems with your code:
Most fundamentally, you forgot to call your randomColor function. You were trying to stringify the function value itself as a CSS color value, which was never going to work. randomColor() is instead what you wanted, the color returned by the function.
Your function would have only worked on the first grid item, because you were using querySelector, which only selects the first HTML element in the collection of matched elements. You instead want to use querySelectorAll, and iterate through the collection, adding the event listener to each.
See working example below, with both fixes made:
//query selectors
const container = document.querySelector('#container');
//Function that creates GRID
function addDivs(rows, cols){
container.style.setProperty('--grid-rows', rows);
container.style.setProperty('--grid-cols', cols);
for (i = 0; i < (rows * cols); i++){
let square = document.createElement("div");
square.classList.add('grid-item');
container.appendChild(square);
}
hoverColor();
}
//function that creates a random color
let randomColor = function() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
//function that changes div color uponed being hovered
function hoverColor() {
let items = document.querySelectorAll('.grid-item');
items.forEach(item => {
item.addEventListener('mouseover', () => {
item.style.backgroundColor = `${randomColor()}`;
});
});
}
//grid creationg
addDivs(16, 16);
:root {
--grid-cols: 1;
--grid-rows: 1;
}
#container {
display: grid;
grid-gap: 0.5em;
grid-template-rows: repeat(var(--grid-rows), 1fr);
grid-template-columns: repeat(var(--grid-cols), 1fr);
border: 3px solid black;
padding: 1em;
}
#container:hover {
box-shadow: 0 5px 5px rgba(0,0,0,0.19), 0 5px 5px rgba(0,0,0,0.23);
}
.grid-item {
padding: 1em;
border: 1px solid #ddd;
text-align: center;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="container"></div>
<script src="script.js"></script>
</body>
</html>
Try this.
Mistakes you did:
You have to attach the eventListener to every element. For starters, querySelector only takes first element. Even if you did use querySelectorAll, you would get a NodeList (sort of an array of Elements), you would still need to loop through each and add the event listener to every one.
In my solution I just add it immediately after you create it in the loop you present in addDivs. Saves looping twice.
You can then reference to the hoverColor function as I did in my example.
In the hoverColor function you will, by default, receive an Event($event) object (in your case MouseEvent). Among multiple properties, the Event object will have a target property which references your Element. You can then modify the style.backgroundColor property to the color of your choice.
Hope it is what you have wanted.
//query selectors
const container = document.querySelector('#container');
//Function that creates GRID
function addDivs(rows, cols){
container.style.setProperty('--grid-rows', rows);
container.style.setProperty('--grid-cols', cols);
for (i = 0; i < (rows * cols); i++){
let square = document.createElement("div");
square.addEventListener('mouseover', hoverColor);
square.classList.add('grid-item');
container.appendChild(square);
}
}
//function that creates a random color
let randomColor = function() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
//function that changes div color uponed being hovered
function hoverColor($event) {
const item = $event.target;
item.style.backgroundColor = `${randomColor()}`;
}
//grid creationg
addDivs(16, 16);
I have found a solution to your problem
//query selectors
const container = document.querySelector('#container');
//Function that creates GRID
function addDivs(rows, cols){
container.style.setProperty('--grid-rows', rows);
container.style.setProperty('--grid-cols', cols);
for (i = 0; i < (rows * cols); i++){
let square = document.createElement("div");
square.classList.add('grid-item');
container.appendChild(square);
}
hoverColor();
}
//function that creates a random color
let randomColor = function() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
//function that changes div color uponed being hovered
function hoverColor() {
let items = document.querySelectorAll('.grid-item'); // Get all the elements with .grid-item (not just the first one
for (let i = 0; i < items.length; i++) { // Add for loop to add an event listener to all .grid-item elements
items[i].addEventListener('mouseover', () => {
items[i].style.backgroundColor = `${randomColor()}`; // randomColor function not being called
// randomColor -> randomColor()
});
}
}
//grid creationg
addDivs(16, 16);
:root {
--grid-cols: 1;
--grid-rows: 1;
}
#container {
display: grid;
grid-gap: 0.5em;
grid-template-rows: repeat(var(--grid-rows), 1fr);
grid-template-columns: repeat(var(--grid-cols), 1fr);
border: 3px solid black;
padding: 1em;
}
#container:hover {
box-shadow: 0 5px 5px rgba(0,0,0,0.19), 0 5px 5px rgba(0,0,0,0.23);
}
.grid-item {
padding: 1em;
border: 1px solid #ddd;
text-align: center;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="container"></div>
<script src="script.js"></script>
</body>
</html>
What I changed
querySelector()
querySelector() to querySelectorAll().
querySelector() will only select the first element it finds in the document querySelectorAll() will select every element in the document with that selector.
randomColor
randomColor to randomColor()
randomColor will return the function randomColor() will run the function.
Added a for loop
The for loop adds an event listener to all the elements with the class name .grid-item.