Dynamicaly Creating a Table with document.createElement and add onclick functions to each tr

I want to add Rows to a Table that already exists and each row has a onclick attribute. The problem is that each row needs to call the function with another parameter. At The moment no matter in what row i click the function is called with the parameter of the last row in the table.

This is how i add the rows to the table :

table = document.getElementById('ProgramTable');
table.style.visibility = "visible";
tableBody = document.getElementById('ProgrammTableBody');
tablelength = jsonObj0.data.map.programs.length;
// Check if there is already a Table, if so
// remove the Table

if (tableexists) {
    removetable();
}

for ( var i = 0; i < tablelength; i++) {
    channel = jsonObj0.data.map.programs[i].programServiceName;
    frequency = jsonObj0.data.map.programs[i].programIdentifier;
    imagelink = "../image/image.jsp?context=tuner&identifier="
        + channel;
    var row = document.createElement("tr");
    row.setAttribute("id", i);

    row.onclick = function() {
        tuneProgram(frequency)
    };
    var channelCell = document.createElement("td");
    var imageCell = document.createElement("td");
    var imageElement = document.createElement("IMG");
    var frequencyCell = document.createElement("td");
    channel = document.createTextNode(channel);
    frequency = document.createTextNode(frequency);
    channelCell.appendChild(channel);
    frequencyCell.appendChild(frequency);
    imageElement.setAttribute("src", imagelink);
    imageElement.setAttribute("width", "40");
    imageElement.setAttribute("height", "40"); // TODO OnError
            // hinzufügen und evtl
            // Css Style für Texte
            // siehe Tabellencode
    imageCell.appendChild(imageElement);
    row.appendChild(channelCell);
    row.appendChild(frequencyCell);
    row.appendChild(imageCell);
    tableBody.appendChild(row);
    }

So the tune function should be called with the specific frequency parameter but it seems like he is overwriting the onclick parameter everytime so the last one is in there for every row. But why is that so? is he adding the onclick Attribute to every row in that table? I don't get it.

Thanks for your help!

Answers


Replace

row.onclick = function() { 
    tuneProgram(frequency) 
};

with

row.onclick = (function(frequency) {return function() {tuneProgram(frequency);};})(frequency);

This "anchors" the value of frequency by creating a new closure for it.


You need to do something like this:

for (var i = 0; i < tablelength; i++) {
   (function(i) {
      //your code here
   })(i);
}

Frequency is being referenced when you click - so if the variable changes, it changes every click element. For example, the first row sets a frequency of one and the last row sets a frequency of two. When the onclick runs it isn't referenced to a value, its referenced to a variable in the chain and gets the current value of two.


because your frequency is a global value, so there is only one frequency that every function refer to it;you can cache it in a closure something like this:

var programTable = document.getElementById('ProgramTable');
programTable.style.visibility = "visible";
programmTableBody = document.getElementById('ProgrammTableBody');
tablelength = jsonObj0.data.map.programs.length;

if (tableexists) {
    removetable();
}

function newTabRow ( table, name, identifier ) {
    var link = "../image/image.jsp?context=tuner&identifier=" + name,
    row = table.insertRow();
    row.innerHTML = '<td>' + name + '</td><td><img width="40" height="40" src="'+link+'" alt="''" /></td><td>'+ identifier +'</td>';
    row.onclick = function  (  ) {
        tuneProgram ( identifier );
    }
}
for (var i = tablelength; i-- > 0; ) {
    program = jsonObj0.data.map.programs[i];
    newTabRow ( programTable, program.programServiceName, program.programIdentifier );
}

Be careful I have a function on top of my page with name "show_field_setting". my function get to value and do something. I have a for loop and in my loop i change 'type' and 'id' for each element. you can see one part inside of my for loop below. finally I add my new element to my div with element id 'my_element_id'. If you want to set a function to your created element you need use something like this:

var new_child = document.createElement('div');new_child.id = id;
new_child.href = "javascript:;";
new_child.onclick = (function (type, id) {
    return function() {
    show_field_setting (type, id);
    };
})(type, id);
document.getElementById('my_element_id').appendChild(new_child);

if you have on argumant in your function only, use this:

var new_child = document.createElement('div');
new_child.href = "javascript:;";
new_child.onclick = (function (your_value) {
    return function() {
    your_function_name (your_value);
    };
})(your_value);
document.getElementById('your_element_id').appendChild(new_child);

finally i don't know why. any way if you are not in loop condition like "while", "for" or even "switch" you can use easy below code line:

var new_child = document.createElement('div');
new_child.href = "javascript:;";
new_child.onclick = function(){your_function_name (your_value_1, your_value_2 , ...)};
document.getElementById('your_element_id').appendChild(new_child);

Have Fun ;) :)


Need Your Help

How to modify "sign in" page using CSS?

html css

I am trying to modify a regular sign in page. I want the input as lines instead of boxes. I am posting the link to the sign in page image I have right now:

Faster way to 'git show' without running a process each time

git perl show

I have a local repository and I would like to view all versions of a file. I can do this crudely by first finding all the commit ids: