I'm trying to insert an onmouseover when creating new rows within my table however it's not appearing. Am I missing something stupid?
var row = document.createElement("TR");
row.id = i;
row.onmouseover = hover(i);
var td1 = document.createElement("TD");
row.appendChild(td1);
tbody.appendChild(row);
The variable 'i' is the current number in the loop. The ID of the row appears fine, but not the onmouseover.
Use an anonymous function to create a closure for the value of i, and make sure you're setting a function to onmouseover, rather than the result of calling a function:
var row = document.createElement("TR");
(function (i) {
row.onmouseover = function () { hover(i) };
})(row.id);
var td1 = document.createElement("TD");
row.appendChild(td1);
tbody.appendChild(row);
Taking a proper look at your code, it appears that you're not actually setting the id attribute of the TR element. However, you might want to avoid that entirely and use this context inside the hover function:
var row = document.createElement("TR");
row.onmouseover = hover;
var td1 = document.createElement("TD");
row.appendChild(td1);
tbody.appendChild(row);
function hover() {
alert(this.rowIndex); // <-- `this` refers to the row element
}
You are assigning the result of the function to the event.
Needs to be something like
row.onmouseover=function(){hover(this);}
And it is better to use this since you have the DOM object and do not have to look up anything.
function hover( row ){
row.style.color = "red";
}
If you still what to go the i way, you need to change your id so it is valid. Ids can not start with a number.
var row = document.createElement("TR");
row.id = "row_i";
row.onmouseover = function(){ hover(this.id); }
var td1 = document.createElement("TD");
row.appendChild(td1);
tbody.appendChild(row);
Maybe try:
row.onmouseover = function() { hover(i); };
Related
I have a table that is dynamically generated via JavaScript based on data from an SQL query. The first cell contains a button that should retrieve the value in the 2nd cell within that row onclick. For some reason, the jQuery onclick event is not firing. No errors are being thrown in the browser.
HTML
...
for (var i=0; i<queryReturned.Result.length; i++) {
var tableRow = document.createElement("tr");
var cell = document.createElement("td");
var button = document.createElement("button"); //Button gets added here
button.type = "button";
button.value = "Remove Alert";
button.className = "buttonSelect"
cell.appendChild(button);
tableRow.appendChild(cell);
//This loop creates the rest of the cells and fills in their data
for (var j=0; j<Object.keys(queryReturned.Result[i]).length; j++) {
var cell2 = document.createElement("td");
var cellText = document.createTextNode(Object.values(queryReturned.Result[i])[j]);
cell2.appendChild(cellText);
tableRow.appendChild(cell2);
}
tableBody.appendChild(tableRow);
}
table.appendChild(tableBody);
table.setAttribute("border", "2");
body.appendChild(table);
...
jQuery
$(document).ready(function(){
$(".buttonSelect").on('click',function(){
var currentRow=$(this).closest("tr");
var col2=currentRow.find("td:eq(1)").html();
alert(col2); //alert for now to test if we grabbed the data
});
});
Reword your event handler function like so:
$(document).on('click', '.buttonSelect', function(){ ... });
so it will work for dynamically added elements as well.
Let us know how it goes!
Firstly the main problem is that you need to use a delegated event handler to attach the click event to the button element.
Also, you're using an odd mix of JS and jQuery. You can massively simplify the table creation logic. Too. Try this:
$(function() {
var $table = $('<table />').appendTo('body'); // this wasn't in your code example, but should look like this
queryReturned.Result.forEach(function(result) {
var $tr = $("<tr />").appendTo($table);
var $td = $("<td />").appendTo($tr);
$('<button class="buttonSelect">Remove Alert</button>').appendTo($td);
for (var j = 0; j < Object.keys(result).length; j++) {
$('<td />').text(result[j]).appendTo($tr);
}
}
$(document).on('click', '.buttonSelect', function() {
var currentRow = $(this).closest("tr");
var col2 = currentRow.find("td:eq(1)").html();
alert(col2);
});
});
I hope you can read my code, I have an XML file on my localhost and I would like it to pull the title and year from that file (it currently has Title, Year, Artist, Price, and Country) while maintaining the H1 and button on the page.
The H1 text and button disappear onClick and I would like it to remain on the same page as the results.
<h1>Show the Album list</h1>
<script>
xmlhttp=new XMLHttpRequest();
xmlhttp.open("GET","cd_catalog.xml",false);
xmlhttp.send();
xmlDoc=xmlhttp.responseXML;
function CdCatalog()
{
document.write("<table border='1'><th>TITLE</th><th>YEAR</th>");
var x=xmlDoc.getElementsByTagName("CD");
for (i=0;i<x.length;i++)
{
document.write("<tr><td>");
document.write(x[i].getElementsByTagName("TITLE")[0].childNodes[0].nodeValue);
document.write("</td><td>");
document.write(x[i].getElementsByTagName("YEAR")[0].childNodes[0].nodeValue);
document.write("</td></tr>");
}
document.write("</table>");
}
</script>
The problem is that you're using document.write for a button's click event, which is after the document's been closed...which means it overwrites everything. Since your page is simple and only has an <h1> and button, it looks like only those things are being hidden, but it would be everything on the page (if you had more).
The solution is to use .appendChild and/or .innerHTML to add the content dynamically. I'll provide a solution in a minute :)
UPDATE:
Since you're using tables, you might as well use the native methods .insertRow and .insertCell that make table creation much easier. Here's an example of what you could use overall:
function CdCatalog(xmlDoc) {
var table = document.createElement("table");
var thead = table.createTHead(); // Where "header" rows go
// `insertRow` creates a <tr> element and appends it to `thead` automatically, returning the element
var tr = thead.insertRow(-1);
var td = document.createElement("th"); // No special method for creating "th" elements
td.innerHTML = "TITLE"; // Set its inner content
tr.appendChild(th); // Add it to the row (which is in the header)
td = document.createElement("td");
td.innerHTML = "YEAR";
tr.appendChild(td);
var x = xmlDoc.getElementsByTagName("CD");
// "tbody" is where a table's content goes, whether you do this explicitly or not
var tbody = table.tBodies[0];
for (var i = 0; i < x.length; i++) {
tr = tbody.insertRow(-1);
// `insertCell` creates a <td> element and appends it to `tr` automatically, returning the element
td = tr.insertCell(-1);
td.innerHTML = x[i].getElementsByTagName("TITLE")[0].childNodes[0].nodeValue;
td = tr.insertCell(-1);
td.innerHTML = x[i].getElementsByTagName("YEAR")[0].childNodes[0].nodeValue;
}
// Actually add the table to the DOM (the <body> element in this case)...you can specify where else to put it
document.body.appendChild(table);
}
// Make sure DOM is ready for manipulation
window.onload = function () {
var btn = document.getElementById("button_id"); // Whatever your button is
// Bind the "click" event for the button
btn.onclick = function () {
// Make your AJAX request
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "cd_catalog.xml", false);
xmlhttp.send();
xmlDoc = xmlhttp.responseXML;
// Pass the result to the function, instead of making everything global and sharing
CdCatalog(xmlDoc);
};
};
And unless I'm mistaken, you can't nest <td> inside of <table>...you must nest them in <tr>...which are nested in <table>
Don't use document.write. It will remove everything you have inside the tag since the document is closed. Do this instead:
document.body.innerHTML += "<td>blah</td>"
-or-
var td = document.createElement("td");
td.innerHTML = "blah"
document.querySelector("table").appendChild(td);
Demo: http://jsfiddle.net/DerekL/AHZ4C/
The code is simple:
var td1 = document.createElement("td");
td1.id="td_radio_"+nr_int+"_"+nr_var2;
td1.style.border = "0";
td1.style.width = "5%";
td1.onclick="adaugare_varianta_simplu(\'"+nr_int+"\',\'"+nr_var2+"\');";
but the function doesn't fire when I click the cell; what am I doing wrong? I'm not using bind because later on there's gonna be a removeAttr working on it so I want it set up as an attribute.
You are assigning a string as event handler so it can not be executed, below is more what you are after I think.
var td1 = document.createElement("td");
td1.id="td_radio_"+nr_int+"_"+nr_var2;
td1.style.border = "0";
td1.style.width = "5%";
td1.onclick = function() {
adaugare_varianta_simplu(nr_int,nr_var2);
};
Think you need this:
td1.onclick="function(){adaugare_varianta_simplu(\'"+nr_int+"\',\'"+nr_var2+"\');}";
You have to wrap the event in a function.
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!
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 ;) :)
Fine, my question is as follows. I am adding rows to a table dynamically using the DOM, and everything goes really well. However, in one of the cells I need to add this calendar: http://www.softcomplex.com/products/tigra_calendar/
When I execute the code to add the calendar, it will create it wherever I place it and mess with everything. What I want to do, is to attach that calendar to the cell and that it executes whenever the nodes enter to the table. This is the code:
function addpago()
{
var i = 0;
//Create a select
var cuota=document.createElement('select');
cuota.name="cuota"+cantpagos;
cuota.id="cuota"+cantpagos;
for(i=1;i<=11;i++)
{
cuota.options[i-1]=new Option("Cuota "+i, i);
}
//Create an input and add an event, this code works correctly
var monto=document.createElement('input');
monto.type='text';
monto.name=monto.id='monto'+cantpagos;
if(monto.addEventListener)
monto.addEventListener("blur", sumpagos, false);
else if(monto.attachEvent)
monto.attachEvent("onblur", sumpagos);
else
monto.onblur = sumpagos;
monto.size=6;
//Create an input
var ncheque = document.createElement('input');
ncheque.type='text';
ncheque.name=ncheque.id='cheque'+cantpagos;
ncheque.size=10;
//Create a select
var bancos = document.createElement('select');
bancos.name=bancos.id='banco'+cantpagos;
bancos.options[0]=new Option("BANCO DE CHILE",1);
bancos.options[1]=new Option("BANCOESTADO",2);
bancos.options[2]=new Option("BANCO DE CRÉDITO E INVERSIONES",3);
bancos.options[3]=new Option("BANCO SANTANDER",4);
bancos.options[4]=new Option("BANCO ITAÚ",5);
//Create an input
var plaza = document.createElement('input');
plaza.type='text';
plaza.name=plaza.id='cheque'+cantpagos;
plaza.size=6;
//Create an input
var fecha = document.createElement('input');
fecha.type='text';
fecha.name=fecha.id='fecha'+cantpagos;
fecha.readOnly=true;
fecha.size=14;
//Create a tr, add several td's and attach each element created before to the child td's
row = document.createElement('tr');
cell = document.createElement('td');
cell.appendChild(cuota);
row.appendChild(cell);
cell = document.createElement('td');
cell.appendChild(monto);
row.appendChild(cell);
cell = document.createElement('td');
cell.appendChild(ncheque);
row.appendChild(cell);
cell = document.createElement('td');
cell.appendChild(bancos);
row.appendChild(cell);
cell = document.createElement('td');
cell.appendChild(plaza);
row.appendChild(cell);
cell = document.createElement('td');
cell.appendChild(fecha);
//I need to add the calendar at this point, but I can't figure out how
cell.appendChild(new tcal ({'formname': 'ingpagos', 'controlname': 'fecha'+cantpagos, 'imgpath': 'www.codesin.cl/Tigra/img/'}));
row.appendChild(cell);
document.getElementById('tabpagos').appendChild(row);
cantpagos++; //Global variable being updated
document.getElementById('cantpagos').value=cantpagos;
}
What should I do? Thanks beforehand...
I've used Tigra Calendar before. Why are you adding it as a node? It's an object you just instantiate, the program takes care of modifying the DOM etc. =)
You do however need to wait to instantiate it until after the input field is IN the DOM =)
...
row.appendChild(cell);
document.getElementById('tabpagos').appendChild(row);
new tcal ({'formname': 'ingpagos', 'controlname': 'fecha'+cantpagos, 'imgpath': 'www.codesin.cl/Tigra/img/'})
Though that imgpath looks suspect so you may need to play with it some =)