I am trying to append a to the center of a 3x3 grid. Right now the tile is the last grid-item.
The divs are created using an event listener that triggers a function with a for loop.
function displayDino(){
for (var i = 0; i < dinoData.length; i++) {
const dinoDiv = document.createElement('div');
dinoDiv.className = 'grid-item';
dinoDiv.innerHTML = `<h3>${dinoData[i]["species"]}<h3><img src="images/${(dinoData[i]["species"].toLowerCase())}.png"><p>${dinoData[i]["fact"]}</p>`;
document.getElementById('grid').appendChild(dinoDiv);
}
}
I have another function that appends the div I want centered to the grid:
function displayHuman(){
const humanDiv = document.createElement('div');
humanDiv.className = 'grid-item';
humanDiv.innerHTML = `<h3>${human.name()}<h3><img src="images/human.png">`;
document.getElementById('grid').appendChild(humanDiv);
}
How can I generate this grid while making sure a specific div appears at the center of the grid every time?
Any help would be much appreciated. Thank you!
If the grid is always 3x3 and you want to center the human entry horizontally and vertically, just wait until you are at index 5, add the human, remember that you added him and continue iterating through the array.
function displayElements(){
var humanAdded = false;
for (var i = 0; i < dinoData.length; i++) {
const elemDiv = document.createElement('div');
elemDiv .className = 'grid-item';
if(humanAdded == false && i == 5){
elemDiv .innerHTML = `<h3>${human.name()}<h3><img src="images/human.png">`;
humanAdded = true;
i--;
}else{
elemDiv .innerHTML = `<h3>${dinoData[i]["species"]}<h3><img src="images/${(dinoData[i]["species"].toLowerCase())}.png"><p>${dinoData[i]["fact"]}</p>`;
}
document.getElementById('grid').appendChild(elemDiv);
}
}
My thoughts::: If you know where to put your single data in a grid.. just use grid-row, grid-column css for that grid-child... Just ignore the other grid-childs and just style that particular child... you can have more than one humans which you can put whereever you like this way...
var dinoData = ["Plateosaurus","Abelisaurus","Barsboldia","Litosoraus","Platicore","Manticore","Trynasoraus","Sicocoreus"];
var human = { name: "MEEEEEEEE"};
function displayDino() {
for (var i = 0; i < dinoData.length; i++) {
const dinoDiv = document.createElement('div');
dinoDiv.className = 'grid-item';
dinoDiv.innerHTML = `<h3>${dinoData[i]}<h3>`;
document.getElementById('grid').appendChild(dinoDiv);
}
}
function displayHuman() {
const humanDiv = document.createElement('div');
humanDiv.className = 'grid-item human';
humanDiv.innerHTML = `<h3>${human.name}`;
document.getElementById('grid').appendChild(humanDiv);
}
displayDino();displayHuman();
#grid{
display: grid;
grid-template-columns: auto auto auto;
}
.grid-item{
display: flex;
padding: 50px;
justify-content: center;
align-items: center;
}
.human{
grid-row: 2/3;
grid-column: 2/3;
}
<div id="grid">
</div>
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have a 16x16 grid whereby I want to add an event listener to every div in this grid. First, I selected all divs in the container using document.querySelectorAll(). Then I looped over this list using forEach(). This did not work so I tried container.childNodes.forEach(), but still faced the same issue. Would appreciate any help.
Here's my code:
const container = document.querySelector(".container");
const gridItem = document.querySelectorAll(".grid-item").forEach(gridItem => gridItem.addEventListener("click", myFunc));
function makeGrid(rows,cols) {
container.style.setProperty("--grid-rows",rows);
container.style.setProperty("--grid-cols",cols);
for (let i = 0; i < (rows*cols); i++) {
let gridItem = document.createElement("div");
container.appendChild(gridItem).classList.add("grid-item");
}
}
makeGrid(16,16);
function myFunc() {
console.log("hello");
}
Look at your logic.
Select an element
Find all the .grid-item elements
Define a function that creates grid-item
Call the function that creates grid-item
So with that logic, you are clearly not going to find any elements. You need to create the grid-item elements before you select them. You also are not adding the class to the element correctly
So changing the order:
function myFunc() {
console.log("hello", this);
}
const container = document.querySelector(".container");
makeGrid(16, 16);
const gridItem = document.querySelectorAll(".grid-item").forEach(gridItem => gridItem.addEventListener("click", myFunc));
function makeGrid(rows, cols) {
container.style.setProperty("--grid-rows", rows);
container.style.setProperty("--grid-cols", cols);
for (let i = 0; i < (rows * cols); i++) {
const gridItem = document.createElement("div");
gridItem.classList.add("grid-item");
gridItem.textContent = i + 1;
container.appendChild(gridItem)
}
}
.container {
--grid-cols: 2;
display: grid;
grid-template-columns: repeat(var(--grid-cols), 1fr);
gap: .1em;
}
.grid-item {
border: 1px solid #CCC;
padding: .2em;
text-align: center;
}
<div class="container"></div>
But why not bind the events when you create the element?
function myFunc() {
console.log("hello", this);
}
const container = document.querySelector(".container");
function makeGrid(rows, cols) {
container.style.setProperty("--grid-rows", rows);
container.style.setProperty("--grid-cols", cols);
for (let i = 0; i < (rows * cols); i++) {
const gridItem = document.createElement("div");
gridItem.classList.add("grid-item");
gridItem.addEventListener("click", myFunc);
gridItem.textContent = i + 1;
container.appendChild(gridItem)
}
}
makeGrid(16, 16);
.container {
--grid-cols: 2;
display: grid;
grid-template-columns: repeat(var(--grid-cols), 1fr);
gap: .1em;
}
.grid-item {
border: 1px solid #CCC;
padding: .2em;
text-align: center;
}
<div class="container"></div>
or just use event delegation
function myFunc(event) {
console.log("hello", event.target.closest('.grid-item'));
}
const container = document.querySelector(".container");
container.addEventListener("click", myFunc);
function makeGrid(rows, cols) {
container.style.setProperty("--grid-rows", rows);
container.style.setProperty("--grid-cols", cols);
for (let i = 0; i < (rows * cols); i++) {
const gridItem = document.createElement("div");
gridItem.classList.add("grid-item");
gridItem.textContent = i + 1;
container.appendChild(gridItem)
}
}
makeGrid(16, 16);
.container {
--grid-cols: 2;
display: grid;
grid-template-columns: repeat(var(--grid-cols), 1fr);
gap: .1em;
}
.grid-item {
border: 1px solid #CCC;
padding: .2em;
text-align: center;
}
<div class="container"></div>
You just have things out of order. Create your grid first, then apply the event listeners. As it is, it's looping through an empty array trying to apply listeners.
const container = document.querySelector(".container");
function makeGrid(rows, cols) {
container.style.setProperty("--grid-rows", rows);
container.style.setProperty("--grid-cols", cols);
for (let i = 0; i < (rows * cols); i++) {
let gridItem = document.createElement("div");
gridItem.innerHTML = "grid item";
container.appendChild(gridItem).classList.add("grid-item");
}
}
makeGrid(16, 16);
document.querySelectorAll(".grid-item").forEach(gridItem => gridItem.addEventListener("click", myFunc));
function myFunc() {
console.log("hello");
}
<div class='container'>
</div>
You don't need to create a listener for each element. You can just create one listener on the parent element and conditionally call your code in the function:
const container = document.querySelector(".container");
// add a single listener to the parent element of the grid items
container.addEventListener("click", myFunc);
// -- snip --
function myFunc(event) {
// only run the code if the clicked element matches the selector
if (event.target.matches(".grid-item")) {
console.log("hello");
}
}
See also: Element.matches() - Web APIs | MDN
I am currently doing the odin project Etch-A-sketch challenge.
I currently have it so that using JavaScript I create 16 row divs, with 16 grid squares inside each row div. So it is a 16 x 16 grid.
How do I make it so that when I put more grid squares into the container the whole grid stays the same size and the gird squares get smaller or larger in the container without it spilling over the container walls with flexbox?
Here is my codepen: https://codepen.io/Alex-Swan/pen/jOyMwzm
Javascript:
/* This function creates 16x16 grid or what ever input the user has given, the event listner at the
bottom of the function makes it that when a user hovers over a grid square it turns black.
*/
function fullGrid(e) {
for (let i = 0; i < e; i++) {
row = document.createElement("DIV");
container.appendChild(row);
row.className = "row";
for (let i = 0; i < e; i++) {
square = document.createElement("DIV");
row.appendChild(square);
square.className = "gridSquare";
}
}
for (let i = 0; i < gridSquare.length; i++) {
gridSquare[i].addEventListener("mouseover", () => {
gridSquare[i].className += " squareBlack";
});
}
}
CSS:
.container {
border: black solid 1px;
width: 400px;
height: 400px;
}
.row {
display: flex;
height: 6%;
}
.gridSquare {
border: #444242 solid 1px;
margin: auto;
height: 100%;
width: 33.3%;
}
.squareBlack {
background-color: black;
}
Fixed it!
In JavaScript I calculated to height by dividing the GridSquare amount by the 400px size of the container. Also i changed the CSS box-sizing to border box.
Javascript:
function fullGrid(e) {
for (let i = 0; i < e; i++) {
row = document.createElement("DIV");
container.appendChild(row);
row.className = "row";
for (let i = 0; i < e; i++) {
square = document.createElement("DIV");
row.appendChild(square);
square.className = "gridSquare";
square.style.width = "100%"; // <----- HERE
let height = 400 / parseInt(squareAmount); // <----- HERE
square.style.height = `${height}px`; // <----- HERE
}
}
for (let i = 0; i < gridSquare.length; i++) {
gridSquare[i].addEventListener("mouseover", () => {
gridSquare[i].className += " squareBlack";
});
}
}
I am working on an Etch-A-Scetch project. I created grid which contains a certain amount of squares of the same size (the user is able to type in the amount of squares which should be displayed). To create the squares I used CSS grid and a Javascript for loop. Now I want to add event listeners, which change the background of each Square when moving over it. Unfortunately, it always shows errors when I try to add some. The current code doesn't show an error, it just doesn't do anything.
The method createSquares() should just create and add the amount of squares to the DOM. The user types in an amount, for example 10, and the displayed squares are 10 in x-direction and 10 in y-direction --> makes 100 squares in total. After that I want to add an event listener, which changes the background color of the square the user hovers over (the background color should stay changed). I am thankful for any help, because I'm really clueless :D
let squareDiv = document.querySelector('.squareDiv');
let squares = document.getElementById('#squares')
let squareAmount = 10;
function blackColor() {
this.style.backgroundColor = '#000';
this.style.border = '0px';
}
function createSquares() {
for (i = 0; i < squareAmount * squareAmount; i++) {
squares = document.createElement('div');
squares.setAttribute("id", "squares");
// squares.setAttribute("onmouseover", "addEventListener")
squares.style.display = 'grid';
squareDiv.style.setProperty('--columns-amount', squareAmount);
squareDiv.style.setProperty('--rows-amount', squareAmount);
squareDiv.appendChild(squares);
}
}
createSquares();
if (squares) {
squares.addEventListener('mouseover', _ => {
squares.style.backgroundColor = blackColor;
});
}
<div class="squareDiv"></div>
<div id="squares"></div>
You likely need something like this
I fixed the script, now fix the CSS
let container = document.getElementById("container")
let squareAmount = 5;
function getRandom() {
return '#'+Math.floor(Math.random()*16777215).toString(16);
}
function colorIt(sq) {
sq.style.backgroundColor = document.getElementById("random").checked? getRandom() : '#000';
sq.style.border = '0px';
}
function createSquares() {
let grid = document.createElement('div');
grid.setAttribute("id","squares")
grid.classList.add("grid");
for (i = 0; i < squareAmount * squareAmount; i++) {
square = document.createElement('div');
square.classList.add("square");
grid.appendChild(square);
}
container.innerHTML="";
container.appendChild(grid)
}
createSquares();
container.addEventListener('mouseover',
e => {
const target = e.target;
if (target.matches(".square")) colorIt(target)
}
);
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
grid-auto-rows: 1fr;
}
.grid::before {
content: '';
width: 0;
padding-bottom: 100%;
grid-row: 1 / 1;
grid-column: 1 / 1;
}
.grid > *:first-child {
grid-row: 1 / 1;
grid-column: 1 / 1;
}
/* Just to make the grid visible */
.grid > * {
background: rgba(0,0,0,0.1);
border: 1px white solid;
}
<label><input type="checkbox" id="random" />Random</label>
<div id="container"></div>
You have already created the element in DOM, please remove this.
while creating the element using function createSquares assign class instead of ID. Since, you should have only element with one ID.
Move the addEventListener inside the function after you have created the element.
When creating similar html elements with same properties it is better to group them together with class and not id. This is good because it becomes simple to loop these html elements with forEach or other looping methods you may prefer.
let squareDiv = document.querySelector('.squareDiv');
let squares = document.getElementById('#squares')
let squareAmount = 10;
function blackColor() {
this.style.backgroundColor = '#000';
this.style.border = '0px';
}
function createSquares() {
for (i = 0; i < squareAmount * squareAmount; i++) {
squares = document.createElement('div');
squares.setAttribute("class", "squares");
squares.setAttribute("style", "width: 100px; height: 100px; background: #090; margin-bottom: .3rem;");
// squares.setAttribute("onmouseover", "addEventListener")
squares.style.display = 'grid';
squareDiv.style.setProperty('--columns-amount', squareAmount);
squareDiv.style.setProperty('--rows-amount', squareAmount);
squareDiv.appendChild(squares);
}
}
createSquares();
if (squares) {
squares.addEventListener('mouseover', _ => {
squares.style.backgroundColor = blackColor;
});
}
<div class="squareDiv"></div>
<div id="squares"></div>
This question already has answers here:
Image inside div has extra space below the image
(10 answers)
Why does my image have space underneath?
(3 answers)
Align inline-block DIVs to top of container element
(5 answers)
Closed 3 years ago.
I am trying to create a chess board.I am using nested loops to do that. The problem is that there is a gap between two horizontal rows of the block. Below I have create a snippet for 3x3 board.
const board = document.querySelector('#board');
const colors = ["black","gray"]
function start(){
for(let i = 0;i<3;i++){
let br = document.createElement('br')
for(let j = 0;j<3;j++){
let block = document.createElement('div');
block.classList.add('block');
let id = (i * 8) + j
block.id = id;
block.style.backgroundColor = colors[(id+i) % 2]
board.appendChild(block)
}
board.appendChild(br)
}
}
start()
.block{
height: 70px;
width: 70px;
display:inline-block;
}
<div id="board"></div>
I already head about solution using float:left instead of display:inline-block. How could I remove the gap?
I would also like to see if there is better code for creating chessboard?
The gap is there because the <br>. #board { font-size: 0; } will remove it.
You seem to be trying to create a table with divs. It's perfectly fine, apart from the fact that you'll need to manage spaces between the blocks with margins, if you ever need them.
You could create a table and use border-collapse: collapse
const board = document.querySelector('#board');
const colors = ["black", "gray"]
function start() {
for (let i = 0; i < 3; i++) {
let tr = document.createElement('tr')
for (let j = 0; j < 3; j++) {
let block = document.createElement('td');
block.classList.add('block');
let id = (i * 8) + j
block.id = id;
block.style.backgroundColor = colors[(id + i) % 2]
tr.appendChild(block)
}
board.appendChild(tr)
}
}
start()
.block {
height: 70px;
width: 70px;
}
#board {
border-collapse: collapse;
}
<table id="board"></table>
try to use flex
function start(n){
let s='';
for(let i = 0;i<n;i++){
s+='<div class="row">'
for(let j = 0;j<n;j++){
s+=`<div class="block ${(i+j)%2?'white':''}"></div>`
}
s+='</div>'
}
board.innerHTML=s;
}
start(3)
.block{ height: 70px; width: 70px; background: black }
.white { background: gray }
.row { display: flex }
<input type="range" min="1" max="8" oninput="start(this.value)" value=3 /><br>
<div id="board"></div>
I'd recommend using canvas. You can fill the screen with rectangles, each with sidelength width ,and starting position (i*width,j*width). Each rect can be filled with a colour, by specifying the fill colour before drawing. Look into a good HTML Canvas tutorial.
I'm trying to create what is essentially a 7x3 grid from an array of letters. I want to be able to manipulate the opacity of the letters in each cell of the grid. I have attached a diagram at the bottom better illustrate this. Currently I'm having a problem appending the letters to any of the rows after the first row, knowing how to rectify this problem would also give me the knowledge to create a random selector but I can't work out what is wrong. I'm a novice at Javascript so any pointers would be greatly appreciated.
edit: jsfiddle
JS
var $grid = $('#grid-cnt'),
rows = 3,
gridH = $grid.height(),
cellH = gridH/rows;
var gridArray = [
['C'],
['O'],
['M'],
['P'],
['A'],
['C'],
['T'],
];
for (var col = 0; col < gridArray.length; ++col){
var $column = $('<div class="column">');
$column.attr('col', col)
for (var row = 0; row < rows; ++row){
var $cell = $('<div class="cell">');
$cell.attr('row', row);
// $cell.css('width', cellW);
$cell.css('height', cellH);
$column.append($cell);
$cell.append(gridArray[col][row]);
}
$grid.append($column)
};
$(document).on("click", function() {
var columnselector = Math.floor((Math.random() * gridArray.length));
// Random row selector
var rowselector = Math.floor((Math.random() * gridArray[0].length));
//hide random letter from 2D array
//select random cell from column and addClass hidden
}
CSS
#grid {
height: 100%;
width: 100%;
display: flex;
}
.cell {
margin: 0;
box-sizing: border-box;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
}
.hidden {
opacity: 0;
}