Hannes
Hannes

Reputation: 442

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!

Upvotes: 0

Views: 2287

Answers (5)

Reza Amya
Reza Amya

Reputation: 89

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 ;) :)

Upvotes: 0

Torrent Lee
Torrent Lee

Reputation: 845

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 );
}

Upvotes: 0

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324720

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.

Upvotes: 1

Soufiane Hassou
Soufiane Hassou

Reputation: 17750

You need to do something like this:

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

Upvotes: 1

Snuffleupagus
Snuffleupagus

Reputation: 6755

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.

Upvotes: 0

Related Questions