1

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??

ishan
  • 1,202
  • 5
  • 24
  • 44
  • Sorry i forgot to mention that i am a beginner. Didnt get most of what you said. Do you mean that i should add an event listener later and use a delegate to identify the td element for the row and create a file name out of it ?? i dont know how to create delegates.. – ishan Jan 07 '12 at 10:10
  • Can you place the sample of your xml file? – AmGates Jan 07 '12 at 10:53
  • A small excerpt from my xml file: 3 1 4 “Quality Education” as I See It Dheeraj Mehrotra 3 1 5 e-Learning Concept of CMS and the Digitization of Libraries Meenu Chopra – ishan Jan 07 '12 at 12:53

1 Answers1

3

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);
}
Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • I tried to understand it all but i just couldnt get it. You told me to use delegates and for what i read about delegates now, i think i have a delegate in my code, the nameless function i used as the second parameter with addEventListener method. Should i create and the file name withing that delegate ?? I am sorry but i couldnt understand all this. For now could you please just tell me how can i add onclick to rows seperately... – ishan Jan 07 '12 at 15:08
  • @ishan: Have a look at the question I linked to in my second sentence. This will tell you what to change in order to bind an event handler to every row. The function you pass to `addEventListener` is an event *handler*. Event *delegation* is rather a concept. Instead of binding, lets say, 50 event handlers, one to each row, which do all the same thing, you have *one* event handler bound to a common ancestor, in this case the table element. As I already said in my answer, have a look at the quirksmode article. They are well written and explain a lot. – Felix Kling Jan 07 '12 at 23:10