Reputation: 1232
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
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