user71346
user71346

Reputation: 733

How to add event listener to each cell in a table?

Let's say I have a grid that looks like this (the numbers inside the cell is just for labeling, it could just be empty cells):

enter image description here

Written in HTML as follows:

<table>
      <tr>
        <td>0 </td>
        <td>1 </td>
      </tr>
      <tr>
        <td>2 </td>
        <td>3 </td>
      </tr>
</table>

There are two things that I would like to do:

  1. Add some JavaScript code that log the number of the cell to the console when each cell is clicked. Here is how I did it:
const cells = document.querySelectorAll('td');
for (var i = 0; i < cells.length; i++) {
  cells[i].addEventListener('click', function () {
    console.log(i);
  });
}

But the console always returns the value 4 wherever I click the table. My questions are:

  1. By adding cells[i].addEventListener in each iteration of the for loop, does it add an event listener for each cell?
  2. Why does the console always return 4 even if I clicked the cells[0], cells[\1], cells[2] or cells[3]?
  3. What should I do to make the console return the desired position in the array cells, i.e. return 0 if I clicked cells[0], return 1 if I clicked cells[\1], return 2 if I clicked cells[2], return 3 if I clicked cells[3]?

Next,

  1. The second thing that I would like to do is to change the colour of each cell depending on the colour that I chose from the colour picker as set by the HTML: <input type="color" id="colorPicker">

Here is how I did it:

const cells = document.querySelectorAll('td');
for (var i = 0; i < cells.length; i++) {
  cells[i].addEventListener('click', function () {    
    const color = document.querySelector('#colorPicker').value;
    cells[i].style.backgroundColor = color;
  });
}

But the colour of the cell did not change.

I don't plan to use jQuery, I would just like to use basic JavaScript that add an event listener to each cell. I have tried to figure some ways out for hours but still clueless in the end. Could somebody please give some help? I really appreciate it, thanks!

Upvotes: 1

Views: 5529

Answers (2)

Yanis-git
Yanis-git

Reputation: 7875

is because you use "i" variable on your callback. And "i" have value : 4 at the end of your loop, so when you click callback, your app use this last value.

Just change your code by :

const cells = document.querySelectorAll('td');
for (var i = 0; i < cells.length; i++) {
  console.log(cells[i].innerText);
  cells[i].addEventListener('click', (event) => {
    console.log(event.target.innerText); // Take the text node from the element who fire the click event.

    // If you don't want to use innerText, you can do like this.
        console.log(
           //We transform querySelectorAll to traversable array. Then we find index of current event target.
           Array.from(document.querySelectorAll('td')).findIndex(e => e === event.target)
        );

  });
}

And for you second case base on colorPicker :

const cells = document.querySelectorAll('td');
for (var i = 0; i < cells.length; i++) {
  cells[i].addEventListener('click', function (event) {    
    const color = document.querySelector('#colorPicker').value;
    event.target.style.backgroundColor = color;
  });
}

live sample

Upvotes: 0

user3094755
user3094755

Reputation: 1641

Since i is incrementing then after the for loop is complete i == cells.length.

in place of...

for (var i = 0; i < cells.length; i++) {
  cells[i].addEventListener('click', function () {
    console.log(i);
  });
}

use...

for (var i = 0; i < cells.length; i++) {
  cells[i].addEventListener('click', function (e) {
    console.log(e.target);
  });
}

And the same for your latter example...

Upvotes: 1

Related Questions