Jump to content

innerHTML vs. the DOM


justsomeguy

Recommended Posts

What does everyone use if you want to change elements on the page? If you have a link like this:<div id="el_id"><a href="java script:void(0);" onclick="show_chunks();">[+] Add Something</a></div>When you click on the link, you want the text to disappear and a form to appear. So, do you use the innerHTML property of the div to replace the text with the form, or do you use the methods in the DOM to add and remove elements in an object-oriented fashion? I've always used innerHTML because it's easy, but the OO aspect of the DOM is appealing. I'm working on a page that I'm planning will make full use of AJAX to do all of the database updating. So what do people prefer, what are the pros and cons you take into account? Does anyone even have much experience using the DOM for things like this?More specifically, here are the functions I have right now to show the form, and then process it. The second function just removes the form at this point without processing the values, but this is the idea. This is what I would do using innerHTML. Using the DOM would definately take a lot more code, but what do people think?

			  <script type="text/javascript">			  function show_add_task()			  {				el = document.getElementById("sched_add_task");				el.innerHTML = "<table style=\"width: 100%; border: 1px solid black; background-color: #6DAAC4;\" cellpadding=\"1\" cellspacing=\"0\">";				el.innerHTML += "<tr>";				el.innerHTML += "<td style=\"vertical-align: top;\" class=\"medium\">";				el.innerHTML += "Task:<br><input type=\"text\" class=\"standard_input\" size=\"20\" maxlength=\"255\" name=\"new_task\" id=\"new_task\">";				el.innerHTML += "</td>";								el.innerHTML += "<td style=\"vertical-align: top;\" class=\"medium\">";				el.innerHTML += "Scheduled Delivery Date (mm/dd/yyyy):<br><input type=\"text\" class=\"standard_input\" size=\"20\" name=\"new_sched_date\" id=\"new_sched_date\">";				el.innerHTML += "</td>";								el.innerHTML += "<td style=\"vertical-align: top;\" class=\"medium\">";				el.innerHTML += "Actual Delivery Date (mm/dd/yyyy):<br><input type=\"text\" class=\"standard_input\" size=\"20\" name=\"new_act_date\" id=\"new_act_date\">";				el.innerHTML += "</td>";				el.innerHTML += "<td style=\"vertical-align: top;\" class=\"medium\">";				el.innerHTML += "Notes:<br><textarea class=\"standard_input\" rows=\"3\" cols=\"40\" name=\"new_notes\" id=\"new_notes\"></textarea>";				el.innerHTML += "</td>";								el.innerHTML += "<td style=\"vertical-align: top;\" class=\"medium\">";				el.innerHTML += "<input type=\"submit\" class=\"standard_input\" value=\"Add Task\" onclick=\"add_new_task();\">";				el.innerHTML += "</td>";				el.innerHTML += "</tr>";				el.innerHTML += "</table>";			  }			  			  function add_new_task()			  {				el = document.getElementById("sched_add_task");								el.innerHTML = "<a href=\"java script:void(0);\" onclick=\"show_add_task();\">[+] Add Task</a>";			  }			  </script>

Here's an alternate question: why the heck does IE render all of the tr and td elements added using innerHTML as inline elements?

Link to comment
Share on other sites

Personally, my current website uses innerHTML to create new elements within a large <div> tag. DOM is used to alter existing elements. Object oriented programming is only unique when you can point out obvious advantages beyond linear programming, hence the DOM method doesn't appeal to me all that much because innerHTML does it just fine and dandy. Until it becomes so advanced past the point that innerHTML seems featureless as opposed to it, I'm not going to go using DOM to dynamically create elements. Though by my recollection, isn't innerHTML part of the HTML DOM; perhaps the thread title needs more distinction, because DOM in general cover HTML, XML, not quite sure of any others though. Digressing, innerHTML is more intuitive than creating elements by other DOM methods. You can use preexisting elements already there, so you know what you're going to get, roughly anyway. I also believe it more flexible as well. And let's not forget about the space saved. A single and craftily coded innerHTML statement could replicate what any number of multiple DOM element creation methods can do. With innerHTML, you're basically coding a string that's in essence HTML code. Screams intuition to me. Sure I don't get the whole node structure when using innerHTML, but mainly because I find that superfluous to my means, I don't think its warrented. When ever I rewrite the contents of an element using innerHTML, I do it by setting innerHTML to a string. Certainly, it can be a very long and complicated string, but if I want to append something, delete something, add another element here, take another one from there, all it requires is some pretty basic string manipulation, which I mainly handle through functions I write myself.As for the last part, I'd question if this is IE6 or IE7 you're using but it most likely doesn't matter. Microsoft couldn't hit standards even if it were a gold filled piñata, and Bill Gates loves gold. Instead, Microsoft creates their own way of doing things, *cough*OpenXML*cough*, and so naturally you'd just expect them to do it with all of their products too. My question to you is why are you surprised? :)

Link to comment
Share on other sites

I usually use the DOM however it should be kept in mind that sometimes innerHTML is actually fast (and sometimes it is not). Depending on the amount of processing you have to do you should test to see which method executes faster.Also keep in mind that creating tables through the DOM in IE is a it weird. It forces you to create a <tbody> also and you add like this <table> -> <tbody> -> <tr> -> <td>If not done in that order the tr and td's will not show.In your specific situation I would write the HTML for the form and hide it in a div then use javascript to reveal it. That is even easier than innerHTML

Link to comment
Share on other sites

I usually use the DOM however it should be kept in mind that sometimes innerHTML is actually fast (and sometimes it is not). Depending on the amount of processing you have to do you should test to see which method executes faster.
I remember reading tests somewhere on the net that innerHTML is always faster then using the create*() methods. It's probably because innerHTML was implemented first (in all browsers).
In your specific situation I would write the HTML for the form and hide it in a div then use javascript to reveal it. That is even easier than innerHTML
And it would degrade well for users without JavaScript. So it is truly a better approach. If you want, you could actually generate the creation link with JavaScript, again for users with JS off.
Link to comment
Share on other sites

When you click on the link, you want the text to disappear and a form to appear. So, do you use the innerHTML property of the div to replace the text with the form, or do you use the methods in the DOM to add and remove elements in an object-oriented fashion? I've always used innerHTML because it's easy, but the OO aspect of the DOM is appealing. I'm working on a page that I'm planning will make full use of AJAX to do all of the database updating. So what do people prefer, what are the pros and cons you take into account?
General advice: If the only tool you have is a hammer, everything starts to look like a nail. To solve a specific problem, use the simplest and most efficient technology you know. But if you are serious on AJAX developement, it is difficult not to use OOP. The XMLHttpRequest object is central in the newer technologies. Related info: W3Schools The XMLHttpRequest ObjectNote AJAX = Asynchronous JAvascript + XmlThen you need to learn the XML family of technologies where the most advanced (PHP) parser in September 2007 is DOM.Related information: The XML family of technologies will revolutionize web linking etc. (Went to the first page of Google on free KW search related to Web Linking. I don't remember the exact term)So my recommendation is, if you are seious about developing web applications with AJAX and XML, you need to learn OOP and DOM. Patterns are a generalization of objects, see the Beta link in my signature. Therefore it is natural to learn OOP befor you learn e.g. Ajax Patterns.
Link to comment
Share on other sites

I remember reading tests somewhere on the net that innerHTML is always faster then using the create*() methods. It's probably because innerHTML was implemented first (in all browsers).And it would degrade well for users without JavaScript. So it is truly a better approach. If you want, you could actually generate the creation link with JavaScript, again for users with JS off.
Take a look here http://www.geekdaily.net/2007/09/14/javasc...out-of-the-dom/ . innerHTML is faster for creating but not for destroying or replacing. It all depends on what is in the container before you add the form.@kgunYou don't need to use AJAX, XML, or PHP to do this simple task. That is just adding complexity (and delay) for nothing.
Link to comment
Share on other sites

General advice: If the only tool you have is a hammer, everything starts to look like a nail. To solve a specific problem, use the simplest and most efficient technology you know.
He mentioned AJAX and OOP. More precisely:
I'm working on a page that I'm planning will make full use of AJAX to do all of the database updating.
My bolding.There is no need to reinvent the wheel. Nicholas C. Zakas, coauthor of "Professional Ajax" has some of the best AJAX related JS libraries that I know of, namely zXml 1.0.2. (Scroll down on the last link).There are a lot of other good free downloads on that page.
Link to comment
Share on other sites

What does everyone use if you want to change elements on the page?
I use a mixture of both. I've found, in some instances, that innerHTML just doesn't work the way that I want it to (namely when creating dropdown menus) so in those cases I use the createElement and createTextNode methods to create them.A DOM way:
var a = document.createElement("a");a.href = "http://www.w3schools.com/";a.appendChild(document.createTextNode("W3Schools"));document.body.appendChild(a);

Also, I don't know how much overhead is involved in accessing the innerHTML property of the element and then appending text to it multiple times. I typically use a string to build the HTML and then assign that string to the innerHTML in one call at the end.

var html = "<a href=\"http://www.w3schools.com/\">";html += "W3Schools";html += "</a>";document.getElementById("sched_add_task").innerHTML = html;

Link to comment
Share on other sites

Though by my recollection, isn't innerHTML part of the HTML DOM; perhaps the thread title needs more distinction, because DOM in general cover HTML, XML, not quite sure of any others though.
innerHTML is a property of objects in the DOM. When I use the term DOM I mean the Document Object Model that the browser exposes to Javascript. The DOM is a tree-like structure of objects, starting with the document object at the root. When I say to use the DOM to add elements to the page, I mean using the create methods to create new nodes on the tree and then assign the properties and attributes to them.
In your specific situation I would write the HTML for the form and hide it in a div then use javascript to reveal it. That is even easier than innerHTML
Yeah, but I'm not going to only have one form on the page that needs this. There could be any number of forms on the page, and the efficient programmer in me tells me that it would be wasteful to output all of the forms if the user isn't going to use them all (they might not use any of them), so I'm looking for the most efficient way of just adding elements to the page in general, whatever the specific circumstances.
And it would degrade well for users without JavaScript. So it is truly a better approach. If you want, you could actually generate the creation link with JavaScript, again for users with JS off.
This is going to require Javascript. For years I've been of the mindset that Javascript should only be used for cosmetic things and not mission-critical things, working with IE4 and Netscape 4 taught me that. But I feel that browser support has gotten to the point that we can rely on the client having support for what we want to do. According to thecounter.com, 94% of people are cruising around with support for Javascript 1.2 or later. I've made the decision that this site is going to require Javascript. I'm taking the plunge. If Javascript is off you can still browse around, but you won't be able to do any of the fun stuff.
If the only tool you have is a hammer, everything starts to look like a nail. To solve a specific problem, use the simplest and most efficient technology you know.
I disagree. The right tool for the job is the right tool for the job. If the only thing I have is a hammer, I'm going to have a ###### of time removing a screw unless I'm willing to expand my tool chest.
So my recommendation is, if you are seious about developing web applications with AJAX and XML, you need to learn OOP and DOM.
I appreciate you posting the links for people, I'm already pretty experienced with OOP. The starting language that I learned in college was C++, and I liked school so much that I spent over 5 years there, so I already think in and have the most experience with OOP. True, writing a string of HTML text to the innerHTML property is pretty straight-forward, but to me it seems much more powerful, and to me intuitive, to simply add new nodes to the tree where I want them, and set the appropriate properties on them. It would take more code, and probably more processing time, but if I want to change the document object model, the logical way seems to be to add and remove objects. I'm not sure what technically happens when you write a string of text to innerHTML, but I'm thinking the reason that IE does not render them as tables means that they aren't being placed into the DOM correctly, if at all. That means I might run into problems if I try to reference the new elements through the DOM, I might not have access to the value property for example. I was hoping that some people who have gone down this road might be able to share their conclusions. I will be doing my own testing with the DOM and see how it works in relation to just using innerHTML.
Nicholas C. Zakas, coauthor of "Professional Ajax" has some of the best AJAX related JS libraries that I know of, namely zXml 1.0.2. (Scroll down on the last link).
That's a good link.
Also, I don't know how much overhead is involved in accessing the innerHTML property of the element and then appending text to it multiple times. I typically use a string to build the HTML and then assign that string to the innerHTML in one call at the end.
Yeah, good point. Regardless of how much overhead it takes to access the property, it's more then just building a string in memory.
Link to comment
Share on other sites

HTML with its static one direction embedded links are fine in many ways. But developing Web 2.0 web applications requires much more flexible linking models. Related link: Transclusion: Fixing Electronic LiteratureRelated Book: XPath, XLink, XPointer, and XML: A Practical Guide to Web Hyperlinking and TransclusionYou have nearly complete control of a document if you mainpulate it using the document object model (DOM).And it is easy to extend the DOM object like you extend SimpleXML functionality.PHP DOM functions.

Link to comment
Share on other sites

I'm not dealing with transclusion here, my question wasn't about linking models or including other documents, I'm trying to dynamically change the structure of a single document. I'm also not dealing with PHP for this, this is a client-side interface issue. The backend I have no problem with. Extending the DOM might be a possibility, but I doubt that it's going to be necessary to extend the DOM to do what I want to do, support should already be there.

You have nearly complete control of a document if you mainpulate it using the document object model (DOM).
Yes, that should be blatantly obvious at this point, I'm asking what the best methods are for changing the structure.Let me restate my situation:The specific application shouldn't matter, but the specific page I'm working on now is an interface to add, remove, and edit tasks in a database. I want everything to be done without reloading the page. There will be a form to add a new task to the list, and you can also click on the existing tasks to edit them in-place or delete them. I'm just saying this as a way of providing an example, the solution I'm looking for will fit for this situation and the other situations I'm going to deal with during the development of this application as well. So the specific problem can be summed up by saying that I am looking for a way to change a document so much that the structure of the final document does not look anything like the original structure, the node tree might be twice as large, or small, by the time the user is finished. I know that two options to do that using Javascript are by accessing the innerHTML property of container objects to add new objects to them (or, a string of code at least), or by using the create functions to create new nodes and append them to their parent nodes. If there are other methods I would be happy to hear about them, or if people have experience using these methods where one of them did not work very well, I would be happy to hear about that situation and why the chosen method didn't work out.
Link to comment
Share on other sites

OK, I've got an innerHTML-less implementation of this working. I ran into two issues, one is that IE will not change an object's type attribute after it has been appended to the page, but IE runs into other issues if you assign properties before appending so the type is the only thing I changed before appending anything. The other issue is that IE uses the className attribute for the CSS class while Opera is fine just using "class". Also, IE doesn't seem to want to apply the cellpadding to the new table. This code runs very quickly under both Opera and IE, in Firefox it is noticeably slower but still fast enough. I know that the Javascript performance in Firefox is not up to par with performance in Opera, IE, or Safari, so I doubt the speed is the fault of the code.

			  function show_add_task()			  {				el = document.getElementById("sched_add_task");				el.innerHTML = "";				tbl = document.createElement('table');				tb = document.createElement('tbody');				r = document.createElement('tr');				c1 = document.createElement('td');				c2 = document.createElement('td');				c3 = document.createElement('td');				c4 = document.createElement('td');				c5 = document.createElement('td');				c1t = document.createTextNode('Text:');				c2t = document.createTextNode('Scheduled Delivery Date:');				c3t = document.createTextNode('Actual Delivery Date:');				c4t = document.createTextNode('Notes:');								c1i = document.createElement('input');				c2i = document.createElement('input');				c3i = document.createElement('input');				c4i = document.createElement('textarea');				c5i = document.createElement('input');				c5i.setAttribute("type", "submit"); // IE will not change type after appending				el.appendChild(tbl);				tbl.appendChild(tb);				tb.appendChild(r);				r.appendChild(c1);				r.appendChild(c2);				r.appendChild(c3);				r.appendChild(c4);				r.appendChild(c5);				c1.appendChild(c1t);				c1.appendChild(c1i);				c2.appendChild(c2t);				c2.appendChild(c2i);				c3.appendChild(c3t);				c3.appendChild(c3i);				c4.appendChild(c4t);				c4.appendChild(c4i);				c5.appendChild(c5i);								tbl.style.width = "100%";				tbl.style.border = "1px solid black";				tbl.style.backgroundColor = "#6DAAC4";				tbl.setAttribute("cellpadding", 1);				tbl.setAttribute("cellspacing", 0);								c1.style.verticalAlign = "bottom";				c2.style.verticalAlign = "bottom";				c3.style.verticalAlign = "bottom";				c4.style.verticalAlign = "bottom";				c5.style.verticalAlign = "bottom";								c1i.setAttribute("className", "standard_input"); //IE				c1i.setAttribute("class", "standard_input");				c1i.style.display = "block";				c1i.setAttribute("size", 40);				c1i.setAttribute("maxlength", 255);				c1i.setAttribute("name", "new_task");				c1i.setAttribute("id", "new_task");								c2i.setAttribute("className", "standard_input"); //IE				c2i.setAttribute("class", "standard_input");				c2i.style.display = "block";				c2i.setAttribute("size", 20);				c2i.setAttribute("maxlength", 10);				c2i.setAttribute("name", "new_sched_date");				c2i.setAttribute("id", "new_sched_date");				c2i.setAttribute("value", "mm/dd/yyyy");								c3i.setAttribute("className", "standard_input"); //IE				c3i.setAttribute("class", "standard_input");				c3i.style.display = "block";				c3i.setAttribute("size", 20);				c3i.setAttribute("maxlength", 10);				c3i.setAttribute("name", "new_act_date");				c3i.setAttribute("id", "new_act_date");				c3i.setAttribute("value", "mm/dd/yyyy");								c4i.setAttribute("className", "standard_input"); //IE				c4i.setAttribute("class", "standard_input");				c4i.style.display = "block";				c4i.setAttribute("rows", 3);				c4i.setAttribute("cols", 50);				c4i.setAttribute("name", "new_notes");				c4i.setAttribute("id", "new_notes");				c5i.setAttribute("className", "standard_input"); //IE				c5i.setAttribute("class", "standard_input");				c5i.setAttribute("value", "Add Task");				c5i.onclick = add_new_task;			  }

The other version I posted above so I won't reproduce it here. Despite the length of this code, I'm inclined to go this route, among other reasons IE displays the structure correctly and I think this will be a better foundation for what I want to do in the future with this. Even if I add a tbody to the innerHTML code above IE still renders everything as inline elements. Anyway, unless I hear a convincing argument to the contrary I will run with this and see what issues pop up.

Link to comment
Share on other sites

Why don't, for the innerHTML method, just give every <tr> and <td> element you have its own id when you create them, or more percisely, in the string assignment? Why not set up the naming system correctly, like table1, table2 and such, create a loop to cycle through all of these using eval(), and then use DOM to change the style to block? No more lines of code necessitated than 5, give or take in that direction. You can always, at least to my experience, force the browser to recognize an element as inline or block depending on your needs. I think I had a similar problem where Firefox and Opera did it correctly but IE made one of my elements made with innerHTML inline, so I set it to block, imposing a forced restriction across all the browsers. I'm away from my primary computer, so I can't recall exactly what it was.

Link to comment
Share on other sites

Right. But I don't want it to be either block or inline, those aren't the only two options. I want it to be table, table-row, and table-cell, but IE does not support those when you try to assign them through CSS or Javascript, it only supports block, inline, none, and list-item. When it's inline everything breaks on a <br> tag, and when it's block everything is on its own line. I want neither of those, I want a table layout. IE gets it right when it renders the table the first time, but try to change a table to inline and then back to table (or block) in IE and see what it does. But you can see my original innerHTML code on the top, if you can get IE to run that and render the table the same way it would if that were static HTML then I'm all ears.

Link to comment
Share on other sites

I'm not dealing with transclusion here, my question wasn't about linking models or including other documents, I'm trying to dynamically change the structure of a single document. I'm also not dealing with PHP for this, this is a client-side interface issue. The backend I have no problem with. Extending the DOM might be a possibility, but I doubt that it's going to be necessary to extend the DOM to do what I want to do, support should already be there.Yes, that should be blatantly obvious at this point, I'm asking what the best methods are for changing the structure.
Ok, but since you mention AJAX, you need a server scripting language if you are not using iFrames or hidden frames (of zero area) for the asynchronous communication with the server.Perheaps a more relevant article is this about Cross-Browser Scripting with importNode() from A LIST apart, a fairly reliable source. <cite>"The frustration of the DOMThough I wouldn't call myself a standards-compliance zealot, I believe standards have their place in development, and I wanted to do this using W3C DOM standards. I know a big question is "Why use the DOM when we have the handy innerHTML property?" The answer, in three parts: 1. The innerHTML property is not standards-compliant. 2. To avoid the XML aspect of this application, I would have to either make a separate call for each part of the data I wanted, or to parse the responseText property that came with the XHR response. 3. Depending on what was contained in the response, innerHTML might not even work correctly".</cite>
Link to comment
Share on other sites

Ok, but since you mention AJAX, you need a server scripting language if you are not using iFrames or hidden frames (of zero area) for the asynchronous communication with the server.
I know, I realize that, I work with server-side scripting every day so that's not a problem for me, that's why I didn't ask about that part. In fact, this is a legacy application where I have to use ASP classic, so PHP really doesn't have anything to do with it. I already have the backend worked out, I'm now focusing strictly on using Javascript to dynamically add and remove large blocks of elements to the web page. It doesn't have anything to do with server-side anything.I appreciate your willingness to help though, that last link isn't specifically about what I'm doing (he's using cloneNode to import existing content, I'm trying to generate new content), but it does contain a couple things that back up the conclusions I was coming to.
Which leads to the third point: innerHTML is not implemented on TBODY elements with Internet Explorer, so if the container element is a table you may encounter problems. innerHTML also has problems rendering SELECT elements in Internet Explorer
That's about all I need to know, I know I'm going to need to use some tables and I know I'll eventually need some select elements as well, so if IE has issues rendering those using innerHTML then I'll just stick to the createElement method instead.
Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...