1

I have a table from which I want to handle click events on each row, depending on the contents of a table cell. The table is (currently) filled dynamically from a static array, although later it will be filled from a database:

var routeTable = document.getElementById('routeTable');
var routes = [
  ['..', '..', '..', "url_1"],
  ['..', '..', '..', "url_2"],
  ['..', '..', '..', "url_3"],
  ['..', '..', '..', "url_4"],
]
for (r = 0; r < routes.length; r++) {
   route = routes[r];
   row = routeTable.insertRow(r+1);
   ....
   ....
   row.addEventListener("click", function () {  display_gpx(route[3]);
   });
}

The trouble is that the parameter passed to the function display_gpx() is always the value "url_4" (from the last route in the table).

I found that the elements for clicking must exist when the document is created , so I looked here (the pure js version) and tried adding

row.className = "myClick";

and changing the eventListener to

 document.addEventListener("click", function (e)
{
    if (e.target.classList.contains("myClick"))
      display_gpx(route[3]);
},false);

but the events don't fire at all.

I think I've solved this before, but returning to javascript after a long break and can't remember the solution!

quilkin
  • 874
  • 11
  • 31

2 Answers2

1

Try this:

(function(url) {
     row.addEventListener("click", function () {  display_gpx(url); });
})(route[3]);

Edit: Snippet replicating the problem with simple code:

var routes = [
  ['..', '..', '..', "url_1"],
  ['..', '..', '..', "url_2"],
  ['..', '..', '..', "url_3"],
  ['..', '..', '..', "url_4"],
]

for (r = 0; r < routes.length; r++) {
   route = routes[r];
   setTimeout(function () {  console.log("not working: " + route[3]); }, 100);
}

for (r = 0; r < routes.length; r++) {
   route = routes[r];
   (function(url) {
       setTimeout(function () {  console.log("working: " + url); }, 100);
   })(route[3]);
}
raul.vila
  • 1,984
  • 1
  • 11
  • 24
1

You mised to add the class myClick to last cell of each row.

The snippet (click on the url...):

var routeTable = document.getElementById('routeTable');
var routes = [
    ['..', '..', '..', "url_1"],
    ['..', '..', '..', "url_2"],
    ['..', '..', '..', "url_3"],
    ['..', '..', '..', "url_4"],
]
for (r = 0; r < routes.length; r++) {
    route = routes[r];
    row = routeTable.insertRow(r);
    for(i=0; i<route.length; i++) {
        newCell = row.insertCell();
        newText  = document.createTextNode(route[i])
        newCell.appendChild(newText);
        if (i == 3) {
            newCell.classList.add('myClick')
        }
    }
}
document.addEventListener("click", function (e) {
    if (e.target.classList.contains("myClick"))
        console.log('classList is: ' + e.target.classList + ' element text is: ' + e.target.textContent);
},false);
<table id="routeTable">
    <tbody>
    </tbody>
</table>
gaetanoM
  • 41,594
  • 6
  • 42
  • 61
  • 1
    Thanks, correct about not adding the class but this solution requires adding all the URLs to the table, and also only works if the URL cell is clicked (which needs to be hidden; the user doesn't need or want to see it). So I've marked @raul.vila as the best answer – quilkin Apr 15 '18 at 17:42