Jump to content

Adding child elements?


davej
 Share

Recommended Posts

The following code seems to work, but is it correct? Thanks.

<!DOCTYPE html><html><head><meta charset="utf-8"><title>add child</title><script>window.onload = function() {assignfn();}var states = new Array('Alabama','Alaska','Arizona','Arkansas','California','Colorado','Connecticut','Utah','Wyoming');function assignfn() {var statesel = document.getElementById('statesel');for (var i=0 ; i<states.length ; i++){var newnode=document.createElement("option");var textnode=document.createTextNode(states[i]);newnode.appendChild(textnode);statesel.appendChild(newnode);newnode.value = states[i];}}//end of assign</script></head><body><p>Data entry:</p><form action="http://localhost" method="get"><select id="statesel" name="state"></select><button type="submit">Submit</button></form></body></html>

http://www.w3schools.com/tags/tag_option.asp

Link to comment
Share on other sites

Or what if you just do the same thing this way?

function assignfn() {var statesel = document.getElementById('statesel');for (var i=0 ; i<states.length ; i++){var newnode=document.createElement("option");statesel.appendChild(newnode);newnode.value = states[i];newnode.innerHTML = states[i];}}//end of assign</script>

Link to comment
Share on other sites

Creating the text node (your first technique) is probably more "correct," but I usually use innerHTML to add text to an element. Curiously, I rarely use it to add HTML to an element. Options are weird, though. There have been methods for adding options dynamically before all the DOM methods were standardized. I think all the browsers support both of your techniques, but I'd check it out anyway. And don't worry about which technique benchmarks faster. Either way should work with no noticeable latency.

Link to comment
Share on other sites

Well, I'm confused when there are always two or three or more ways to do the same thing. For example if I can simply say...

newnode.id = 'id123';newnode.className = 'myclass';

...to set valid attributes by name then why would I ever need createAttribute() ? http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_document_createattribute

Link to comment
Share on other sites

...to set valid attributes by name then why would I ever need createAttribute() ?
Creating and setting an attribute actually causes an HTML tag to contain an attribute. You can read it if you examine the innerHTML or use the inspect tool in your browser. Setting a property just using dot notation doesn't do that. Likewise, if you write a non-standard attribute in your HTML document, you probably can't read it using dot notation, but you should be able to read it using getAttribute.
Link to comment
Share on other sites

Well, just to have a clear example and avoid confusion, if I start with...

<select name="state" id="statesel"></select>

...and I'm looking at creating the option tags here...

<select name="state" id="statesel">  <option value="AL">Alabama</option>  <option value="AK">Alaska</option>  <option value="AZ">Arizona</option></select>

I seem to be able to successfully add class, id, value for any of these option tags once the option node has been created by simply setting them with .id .className and .value. The textname is added with .innerHTML. Of course I'm not testing this with all browsers. Mostly I'm just looking at Firebug in Firefox. Maybe this simple approach could fail in some other browsers? Thanks

Edited by davej
Link to comment
Share on other sites

To add text for option element you should use .text, you should not use .innerHTML for ANY form element, especially not for textarea, where .value can be used.
You are right -- they show .text in the property list for the <option> tag...http://www.w3schools..._obj_option.asp ... but wait... the W3Schools page then says: "The Option object also supports the standard properties and events." Why do these property and method lists seem to get broken up? Edited by davej
Link to comment
Share on other sites

because properties and events are two different things. the events list is essentially methods that the element supports for doing event handling.

Edited by thescientist
Link to comment
Share on other sites

because properties and events are two different things. the events list is essentially methods that the element supports for doing event handling.
Ok, but what I meant is this... as an example... I go here... http://www.w3schools.com/jsref/dom_obj_core_document.asp ...and there is no listing for a method document.getElementsByName() But then I go here... http://www.w3schools.com/jsref/dom_obj_document.asp ...and there is an entry for the method document.getElementsByName() So where should I go to find the ultimate list of all methods that can be appended to a particular element? Thanks
Link to comment
Share on other sites

  • 4 weeks later...

Since I'm back on this same topic I guess I'll resurrect this old thread. If I am adding a table to a form can I or should I -- build the entire table object -- and then add it as a child of the form? It seems strange to create an element and add children to it when it is not yet part of the document but is instead floating around in La-la land. Or should I add the table to the form and then add children to build it? Or is one way better than the other? Thanks.

Edited by davej
Link to comment
Share on other sites

In the old days, when computers and browsers were slower, the accepted wisdom was to create the entire object, with all its children, before adding it to the DOM. This eliminated flicker as the bits and pieces popped into existence. Latency of this kind is no longer a problem (unless your table has thousands of elements, I guess) but I still do stuff like that old-school. La-la land has never been anything to worry about. It can even be a handy resource at times.

Link to comment
Share on other sites

My first iteration is simply a crude version of what I want using innerHTML. It does not seem to correctly create the table or correctly create the links/anchors.

window.onload = function(){var out = document.getElementById('out');out.innerHTML = '';var tot = Number(filenames.length);var i = 0;while( i<(tot-7) ){ //print another table if there are eight more photos remainingout.innerHTML += '<table border="1"><tr>';for (var col=0 ; col<4 ; col++){out.innerHTML += '<td><a href="photos_t/'+ filenames[i] +'">';out.innerHTML += '<img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a></td>';i++;}out.innerHTML += '</tr><tr>';for (var col=0 ; col<4 ; col++){out.innerHTML += '<td><a href="photos_t/'+ filenames[i] +'">';out.innerHTML += '<img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a></td>';i++;}out.innerHTML += '</tr></table><br/>';}//end while}//end onload

My next iteration is a little better. It actually works...

window.onload = function(){var out = document.getElementById('out');out.innerHTML = '';var tot = Number(filenames.length);var i = 0;while( i<(tot-7) ){ //print another table if there are eight more photos remainingvar newTable = document.createElement("table");var row0 = newTable.insertRow(0);var cell00 = row0.insertCell(0);var cell01 = row0.insertCell(1);var cell02 = row0.insertCell(2);var cell03 = row0.insertCell(3);cell00.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;cell01.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;cell02.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;cell03.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;var row1 = newTable.insertRow(1);var cell10 = row1.insertCell(0);var cell11 = row1.insertCell(1);var cell12 = row1.insertCell(2);var cell13 = row1.insertCell(3);cell10.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;cell11.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;cell12.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;cell13.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;out.appendChild(newTable); //append the table to the out divvar br = document.createElement("br");out.appendChild(br); //append <br/> to the out div}//end while}//end onload

Edited by davej
Link to comment
Share on other sites

If you're using innerHTML then you need to write the entire string at once. Build the HTML string in another variable and once you have all the HTML, then write to innerHTML. The browser will automatically "fix" innerHTML, so if you write an incomplete string to it it's going to add any missing things like closing tags to compete the elements. DD was talking about creating and appending nodes using the DOM methods, not using innerHTML. You're not creating new DOM nodes, you're creating a string of HTML and then writing it to the element.

Link to comment
Share on other sites

Ok, I will go back and try creating the entire string before using innerHTML. I'm trying to proceed from the simple-minded approach to the more proper child-node approach. Currently I'm at this point...

window.onload = function(){var out = document.getElementById('out');out.innerHTML = '';var tot = Number(filenames.length);var i = 0;while( i<(tot-7) ){ //print another table if there are eight more photos remainingvar newTable = document.createElement("table");var newAttrib = document.createAttribute("border");newAttrib.value = "1";newTable.setAttributeNode(newAttrib); //append border="1" to the tablevar row0 = newTable.insertRow(0);var cell00 = row0.insertCell(0);var cell01 = row0.insertCell(1);var cell02 = row0.insertCell(2);var cell03 = row0.insertCell(3);cell00.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;cell01.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;cell02.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;cell03.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;var row1 = newTable.insertRow(1);var cell10 = row1.insertCell(0);var cell11 = row1.insertCell(1);var cell12 = row1.insertCell(2);var cell13 = row1.insertCell(3);cell10.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;cell11.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;cell12.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;cell13.innerHTML = '<a href="photos_t/'+ filenames[i] +'"><img alt="'+ filenames[i] +'" src="photos_t/'+ filenames[i] +'" width="200"/></a>';i++;out.appendChild(newTable); //append the table to the out divvar br = document.createElement("br");out.appendChild(br); //append <br/> to the out div}//end while}//end onload

Link to comment
Share on other sites

What you have here ^^ is more correct. My only concern is that it repeats a lot of the same code. Some of the steps could be modularized, especially the construction of the innerHTML strings.

Link to comment
Share on other sites

Sure. Just use createElement to make the <a> and <img> elements. Then set their attributes. The only thing that varies is the value of i, so build a little function that accepts i as an argument and returns the populated <a> as an element object.

Link to comment
Share on other sites

Here is my compressed version that still uses innerHTML...

window.onload = function(){var out = document.getElementById('out');out.innerHTML = '';var tot = Number(filenames.length);var i = 0;while( i<(tot-7) ){ //print another table if there are eight more photos remainingvar newTable = document.createElement("table");var newAttrib = document.createAttribute("border");newAttrib.value = "1";newTable.setAttributeNode(newAttrib); //append border="1" to the tablevar row = [newTable.insertRow(0), newTable.insertRow(1)];var cell = [];for (var j=0 ; j<4 ; j++){cell[j] = row[0].insertCell(j);}var strs = ['<a href="photos_t/','"><img alt="','" src="photos_t/','" width="200"/></a>'];for (var j=0 ; j<4 ; j++){cell[j].innerHTML = strs[0]+ filenames[i] +strs[1]+ filenames[i] +strs[2]+ filenames[i] +strs[3];i++;}for (var j=0 ; j<4 ; j++){cell[j] = row[1].insertCell(j);}for (var j=0 ; j<4 ; j++){cell[j].innerHTML = strs[0]+ filenames[i] +strs[1]+ filenames[i] +strs[2]+ filenames[i] +strs[3];i++;}out.appendChild(newTable); //append the table to the out divvar br = document.createElement("br");out.appendChild(br); //append <br/> to the out div}//end while}//end onload

Link to comment
Share on other sites

This isn't working... Is the anchor a child of the cell and the image a child of the anchor?

window.onload = function(){var out = document.getElementById('out');out.innerHTML = '';var tot = filenames.length;var i = 0;while( i<(tot-7) ){ //print another table if there are eight more photos remainingvar newTable = document.createElement("table");var newAttrib = document.createAttribute("border");newAttrib.value = "1";newTable.setAttributeNode(newAttrib); //append border="1" to the tablevar row = [newTable.insertRow(0), newTable.insertRow(1)];var cell = [row[0].insertCell(0),row[0].insertCell(1),row[0].insertCell(2),row[0].insertCell(3)];var strs = ['<a href="photos_t/','"><img alt="','" src="photos_t/','" width="200"/></a>'];for (var j=0 ; j<4 ; j++){//cell[j].innerHTML = strs[0]+ filenames[i] +strs[1]+ filenames[i] +strs[2]+ filenames[i] +strs[3];cell[j].appendChild(cellGuts(i));i++;}for (var j=0 ; j<4 ; j++){cell[j] = row[1].insertCell(j);}for (var j=0 ; j<4 ; j++){//cell[j].innerHTML = strs[0]+ filenames[i] +strs[1]+ filenames[i] +strs[2]+ filenames[i] +strs[3];cell[j].appendChild(cellGuts(i));i++;}out.appendChild(newTable); //append the table to the out divvar br = document.createElement("br");out.appendChild(br); //append <br/> to the out div}//end while}//end onloadfunction cellGuts(i){var newImg = document.createElement("image");var newAnchor = document.createElement("anchor");var newAttrib = document.createAttribute("alt");newAttrib.value = filenames[i];newImg.setAttributeNode(newAttrib);newAttrib = document.createAttribute("src");newAttrib.value = 'photos_t/' + filenames[i];newImg.setAttributeNode(newAttrib);newAttrib = document.createAttribute("width");newAttrib.value = '200';newImg.setAttributeNode(newAttrib);newAttrib = document.createAttribute("href");newAttrib.value = 'photos_t/' + filenames[i];newAnchor.setAttributeNode(newAttrib);newAnchor.appendChild(newImg);return newAnchor;}

Link to comment
Share on other sites

This doesn't work either...

window.onload = function(){var out = document.getElementById('out');out.innerHTML = '';var tot = filenames.length;var i = 0;var child1;while( i<(tot-7) ){ //print another table if there are eight more photos remainingvar newTable = document.createElement("table");var newAttrib = document.createAttribute("border");newAttrib.value = "1";newTable.setAttributeNode(newAttrib); //append border="1" to the tablevar row = [newTable.insertRow(0), newTable.insertRow(1)];var cell = [row[0].insertCell(0),row[0].insertCell(1),row[0].insertCell(2),row[0].insertCell(3)];//var strs = ['<a href="photos_t/','"><img alt="','" src="photos_t/','" width="200"/></a>'];for (var j=0 ; j<4 ; j++){//cell[j].innerHTML = strs[0]+ filenames[i] +strs[1]+ filenames[i] +strs[2]+ filenames[i] +strs[3];child1 = cellGuts(i);cell[j].appendChild(child1);i++;}for (var j=0 ; j<4 ; j++){cell[j] = row[1].insertCell(j);}for (var j=0 ; j<4 ; j++){//cell[j].innerHTML = strs[0]+ filenames[i] +strs[1]+ filenames[i] +strs[2]+ filenames[i] +strs[3];child1 = cellGuts(i);cell[j].appendChild(child1);i++;}out.appendChild(newTable); //append the table to the out divvar br = document.createElement("br");out.appendChild(br); //append <br/> to the out div}//end while}//end onloadfunction cellGuts(i){var newImg = document.createElement("image");var newAnchor = document.createElement("anchor");var newAttrib = document.createAttribute("alt");newAttrib.value = filenames[i];newImg.setAttributeNode(newAttrib);newAttrib = document.createAttribute("src");newAttrib.value = 'photos_t/' + filenames[i];newImg.setAttributeNode(newAttrib);newAttrib = document.createAttribute("width");newAttrib.value = '200';newImg.setAttributeNode(newAttrib);newAttrib = document.createAttribute("href");newAttrib.value = 'photos_t/' + filenames[i];newAnchor.setAttributeNode(newAttrib);newAnchor.appendChild(newImg);return newAnchor;}

Link to comment
Share on other sites

My goal was to write some JS that would make it much quicker and easier for me to post a new page of trip photos. Here is my original manually-constructed page: http://www.stlnetwor...013/photos.html Here is my JS-driven page: http://www.stlnetwor...est/photos.html Here is the latest non-working version: http://www.stlnetwork.net/kayak/whitewater/test/photos4.html

Edited by davej
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...