-2

So basically I have functions that creates a grid. When I hover over a particular cell I want the cell to be filled black. But the fill should remain in the cell after the hover. How do I do that using JS?

I'm new to JS and this is my first time asking a programming related question so I apologize if my question is not clear enough.

const container = document.querySelector('#container');
let rows = document.getElementsByClassName('grid-row');
let cells = document.getElementsByClassName('grid-column');

defaultGrid();


function defaultGrid() {
  createRow(18);
  createColumn(18);
}

function createRow(rowNum) {
  for (let i = 0; i < rowNum; i++) {
    let row = document.createElement('div');
    container.appendChild(row).className = 'grid-row';
  }
}

function createColumn(cellNum) {
  for (let i = 0; i < rows.length; i++) {
    for (let j = 0; j < cellNum; j++) {
      let newCell = document.createElement('div');
      rows[j].appendChild(newCell).className = 'grid-column';
    }
  }

}
body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.grid-column {
  display: inline-block;
  border: 1px solid black;
  min-height: 20px;
  min-width: 20px;
  margin-left: 2px;
  margin-top: 2px;
}

#container {
  border: 5px solid chartreuse;
}

.fill {
  background: black;
}
<h2>test</h2>

<div id="container">
</div>
Chris-SL
  • 1
  • 2
  • 2
    Where is your hovering code? – callback Aug 30 '21 at 12:57
  • 1
    There is no reason code which adds a class has to remove it; please show the code you have which does so. – Heretic Monkey Aug 30 '21 at 13:03
  • Hi, your actual question seems to be "how do I add a `mouseenter` event listener (or any other type) to a bunch of divs?" You'll find a bunch of existing answers for that. –  Aug 30 '21 at 13:07
  • Duplicate: [How to addEventListener to multiple elements in a single line](https://stackoverflow.com/questions/40956717/how-to-addeventlistener-to-multiple-elements-in-a-single-line) –  Aug 30 '21 at 13:08
  • @ChrisG yea that is what I was looking for, thanks! – Chris-SL Aug 30 '21 at 13:11
  • @ChrisG Not a delegation in sight on that link – mplungjan Aug 30 '21 at 13:14
  • @mplungjan True, and delegation is a better way to do this, but you have to start with the basics, I guess? OP didn't know how to assign an event handler in the first place. –  Aug 30 '21 at 14:01

3 Answers3

2

Like this:

  • Delegate from the container

  • Test the target

  • I use mouseover for the delegation and add your already defined class that way there is no need to add eventlisteners to each cell

    container.addEventListener("mouseover",function(e) {
      const tgt = e.target;
      if (tgt.classList.contains("grid-column")) tgt.classList.add("fill")
    })
    

const container = document.querySelector('#container');
let rows = document.getElementsByClassName('grid-row');
let cells = document.getElementsByClassName('grid-column');

defaultGrid();


function defaultGrid() {
  createRow(18);
  createColumn(18);
}

function createRow(rowNum) {
  for (let i = 0; i < rowNum; i++) {
    let row = document.createElement('div');
    container.appendChild(row).className = 'grid-row';
  }
}

function createColumn(cellNum) {
  for (let i = 0; i < rows.length; i++) {
    for (let j = 0; j < cellNum; j++) {
      let newCell = document.createElement('div');
      rows[j].appendChild(newCell).className = 'grid-column';
    }
  }
}
container.addEventListener("mouseover",function(e) {
  const tgt = e.target;
  if (tgt.classList.contains("grid-column")) tgt.classList.add("fill")
})
body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.grid-column {
  display: inline-block;
  border: 1px solid black;
  min-height: 20px;
  min-width: 20px;
  margin-left: 2px;
  margin-top: 2px;
}

#container {
  border: 5px solid chartreuse;
}

.fill {
  background: black;
}
<h2>test</h2>

<div id="container">
</div>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
0

Since you already declared a fill class, just need to add this line to your createColumn function.

function createColumn(cellNum) {
for (let i = 0; i < rows.length; i++) {
 for (let j = 0; j < cellNum; j++) {
   let newCell = document.createElement('div');
   newCell.onmouseenter = () => newCell.classList.add("fill");  ----> Add this line
   rows[j].appendChild(newCell).className = 'grid-column';
  }
 }
}

This will append the class name to the cell element.

Gourav Saini
  • 632
  • 6
  • 11
0

Add the event listener to your cell creation loop:

const container = document.querySelector('#container');
let rows = document.getElementsByClassName('grid-row');
let cells = document.getElementsByClassName('grid-column');

defaultGrid();


function defaultGrid() {
  createRow(18);
  createColumn(18);
}

function createRow(rowNum) {
  for (let i = 0; i < rowNum; i++) {
    let row = document.createElement('div');
    container.appendChild(row).className = 'grid-row';
  }
}

function createColumn(cellNum) {
  for (let i = 0; i < rows.length; i++) {
    for (let j = 0; j < cellNum; j++) {
      let newCell = document.createElement('div');
      /**
      * add eventlistener
      */
      newCell.addEventListener('mouseover',function() { 
        newCell.classList.add('fill');
      });
      
      rows[j].appendChild(newCell).className = 'grid-column';
    }
  }

}
body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.grid-column {
  display: inline-block;
  border: 1px solid black;
  min-height: 20px;
  min-width: 20px;
  margin-left: 2px;
  margin-top: 2px;
}

#container {
  border: 5px solid chartreuse;
}

.fill {
  background: black;
}
<h2>test</h2>

<div id="container">
</div>