Search code examples
javascripthtmlcssevent-listeneronmousedown

How to change color of an html table cell when mouse is down, based on which cell it is hovering over?


Essentially, I want a user to be able to click and hold down their mouse and scroll over any number of cells in the table, as soon as they scroll over a cell it should change color. The thing is that when the user regularly clicks a cell I want the cell to change color, and I have a separate event listener that does that.

This is my table in html

<table class="c-table" onmousedown="hoverColorFill()">

and this is the js function I made to try to handle the hover on mousedown situation I described this:

function hoverColorFill(){
    elements = document.querySelectorAll(':hover');
    for(let i=0; i<elements.length; i++){
    elements[i].style.backgroundcolor = colorEl.value
       }
}

this is the code I have for when someone simply clicks I cell:

table.addEventListener('click', (event) => {
  const rows = document.querySelectorAll('tr');
  const rowsArray = Array.from(rows);
  const rowIndex = rowsArray.findIndex(row => row.contains(event.target));
  const columns = Array.from(rowsArray[rowIndex].querySelectorAll('td'));
  const columnIndex = columns.findIndex(column => column == event.target);
  document.querySelector(".c-table").tBodies[0].rows[rowIndex-1].cells[columnIndex].style.backgroundColor = colorEl.value
})

it doesn't seem that the hoverColorFill() function works, when I drag my mouse over my table the function gets called (it can print to the console) but it doesn't change the colors. My click event listener function completely properly, but it does occasionally give this error: Uncaught TypeError: Cannot read properties of undefined (reading 'style')at HTMLTableElement. but the function that is not working doesn't throw any errors.

Edit: the reason I am not using an eventListener here is because I couldn't figure out how to do it so that it pays attention to both the hover and the mouseover.


Solution

  • colorTd() function checks if you've clicked on a td and then adds a class to it
    It'll active when you click on it or drag your mouse along when you're clicking
    Whether you're dragging your mouse while clicked is checked by onmousedown and onmouseup. It is stored in mouseIsDown

    When you're mouse is over the table (determined by onmouseover ) and when mouseIsDown is true, colorTd() function will execute, giving tds a class

    const table = document.querySelector("table");
    const className = "selected";
    let mouseIsDown = false;
    
    const colorTd = (e) => (e.target.tagName = "TD" && e.target.classList.add("selected"));
    table.onclick = (e) => colorTd(e);
    
    document.onmousedown = (e) => {
      mouseIsDown = true;
      colorTd(e);
    };
    
    document.onmouseup = () => (mouseIsDown = false);
    table.onmouseover = (e) => mouseIsDown && colorTd(e);
    td {
      cursor: pointer;
      font-size: 22px;
    }
    
    td.selected {
      background-color: lightblue;
    }
    
    table::selection,
    tr::selection,
    td::selection {
      background-color: transparent;
    }
    <table>
      <tr>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
      </tr>
      <tr>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
      </tr>
      <tr>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
      </tr>
      <tr>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
      </tr>
      <tr>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
        <td>Cell</td>
      </tr>
    </table>