How can I detect if a mouse click was not done on a table row?
I created this table, which can be modified on the fly and highlights the selected row, if selected. Now I try to establish a function, which removes the row highlighting as soon as a mouse click was not done in one of those table rows. I do not want to add another eventListener for the remaining body or other html elements located in the background.
I thought about the following:
if (row highlighted) { next outside click removes row highlight }
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Table Test</title> <!-- d3.js framework --> <script src="https://d3js.org/d3.v6.js"></script> <!-- jquery import--> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <!-- fontawesome stylesheet https://fontawesome.com/ --> <script src="https://kit.fontawesome.com/39094309d6.js" crossorigin="anonymous"></script> </head> <style> #myTable { border-collapse: collapse; } #myTable td { border: 1px solid black; padding: 8px; } #delRow { width: auto; height: 30px; } </style> <body> <table id="myTable"> <th> Property </th> <th> Value </th> <tbody> <!-- filled by script --> </tbody> </table> <button id="dataToArray">dataToArray</button> <script> data = [ { "property": "animal", "value": "dog" }, { "property": "car", "value": "audi" }, { "property": "snacks", "value": "chips" } ] //populate table var myTable = document.getElementById("myTable") for (var i = 0; i < data.length; i++ ) { var row = `<tr> <td contenteditable='true'>${data[i].property}</td> <td contenteditable='true'>${data[i].value}</td> </tr>` myTable.innerHTML += row } //higlight row let lastClickedRow = null for (var i = 0, tableRow; tableRow = myTable.rows[i]; i++) { tableRow.addEventListener("click", function() { if (lastClickedRow != null) { lastClickedRow.style.backgroundColor = null } lastClickedRow = this lastClickedRow.style.backgroundColor = "greenyellow" }) } //get table data var dataToArray = document.getElementById("dataToArray") dataToArray.addEventListener("click", function() { var exportData = [] $("table#myTable tr").each(function() { var rowDataObject = new Object var actualData = $(this).find("td"); if (actualData.length > 0) { rowDataObject.property = actualData[0].innerText; rowDataObject.value = actualData[1].innerText; exportData.push(rowDataObject) }; }) console.log(exportData) }) </script> </body> </html>
Advertisement
Answer
Much simpler solution for this will be
- Add an event listner to the click event of body.
- Check whether the ckick event is either on the button or on the table with
Node.contains
in Javascript Reference - If the table row and button is not clicked, reset the color.
data = [ { "property": "animal", "value": "dog" }, { "property": "car", "value": "audi" }, { "property": "snacks", "value": "chips" } ] //populate table var myTable = document.getElementById("myTable") for (var i = 0; i < data.length; i++) { var row = `<tr> <td contenteditable='true'>${data[i].property}</td> <td contenteditable='true'>${data[i].value}</td> </tr>` myTable.innerHTML += row } //higlight row let lastClickedRow = null; function resetColor() { for (var i = 0, tableRow; tableRow = myTable.rows[i]; i++) { tableRow.style.backgroundColor = null; } } for (var i = 0, tableRow; tableRow = myTable.rows[i]; i++) { tableRow.addEventListener("click", function (e) { if (lastClickedRow != null) { lastClickedRow.style.backgroundColor = null } lastClickedRow = this lastClickedRow.style.backgroundColor = "greenyellow"; }) } var tableElement = document.getElementById('myTable'); var buttonElement = document.getElementById('dataToArray'); document.addEventListener('click', function(event) { const isInsideClicked = tableElement.contains(event.target) || buttonElement.contains(event.target); if(!isInsideClicked) { resetColor(); } }) //get table data var dataToArray = document.getElementById("dataToArray") dataToArray.addEventListener("click", function (e) { var exportData = [] $("table#myTable tr").each(function () { var rowDataObject = new Object var actualData = $(this).find("td"); if (actualData.length > 0) { rowDataObject.property = actualData[0].innerText; rowDataObject.value = actualData[1].innerText; exportData.push(rowDataObject) }; }) console.log(exportData) })
#myTable { border-collapse: collapse; } #myTable td { border: 1px solid black; padding: 8px; } #delRow { width: auto; height: 30px; }
<table id="myTable"> <th> Property </th> <th> Value </th> <tbody> <!-- filled by script --> </tbody> </table> <button id="dataToArray">dataToArray</button>