ishan
ishan

Reputation: 1232

how to implement different eventlistener for each row in my table generated through javascript

My javascript code pulls out data from a xml file and prepares a data grid using that data. For each row of my table, i want to set the eventlistener property to open a file whose name is actually the "pid" field which is in that row. The code is below:

//Some code to get the xml file
var x = [];
      xmlhttp=new XMLHttpRequest();

    xmlhttp.open("GET","newdata.xml",false);
    xmlhttp.send();
    xmlDoc=xmlhttp.responseXML;

//Now creating each row from the data which i have pushed into array x

    var file_pid = "";
    for (i=0;i<x.length;i++)
      {
var file_pid = "papers/" + x[i].getElementsByTagName("pid")[0].childNodes[0].nodeValue + ".pdf";

//create each row and corresponding attributes
      tr = document.createElement('tr');
      tr.addEventListener('click',function() {window.open(file_pid)},false);

Now the problem is that the event listener is added but each row opens 1 file, 8.pdf, which is the last record in the xml file. What should i do to make it open only the file name assigned to that perticular row??

Upvotes: 1

Views: 588

Answers (1)

Felix Kling
Felix Kling

Reputation: 816840

It's because you are creating a closure in a loop. Have a look at this question for an explanation and solution.

However, depending on the number of rows, I think it would be better to store the pid as data- attribute on the row and only bind one event handler to the table (event delegation), when then retrieves the corresponding pid. For more information about event handling, I suggest to read the excellent articles on quirksmode.org.

Example:

// table is a reference to the table:

function closest(element, tag) {
    tag = tag.toLowerCase();
    while(element && element.tagName.toLowerCase() !== tag) {
        element = element.parentNode;
    }
    return element;
}


table.addEventListener('click', function(event) {
    var row = closest(event.target, 'tr'), pid;
    if(row && (pid = row.getAttribute('data-pid')) {
        window.open(pid);
    }
});

Keep in mind that event handling is different in W3C-compatible browsers and IE (before IE9). So in IE you have to use attachEvent, the event object is not passed to the handler, etc. If you want to be cross-browser compatible, you could just assign the handler to the onclick property:

table.onclick = function(event) {
    event = event || window.event;
    target = event.target || event.srcElement;
    // proceed similarly as shown above
}

You then append the rows somehow like this:

var file_id, tr;

for (i=0;i<x.length;i++) {
    file_pid = "...";

    tr = document.createElement('tr');
    // or tr = table.insertRow(-1);
    tr.setAttribute('data-pid', pid);
}

Upvotes: 3

Related Questions