<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Think Vitamin &#187; Hallvord R. M. Steen</title>
	<atom:link href="http://thinkvitamin.com/author/hallvord-r-m-steen/feed/" rel="self" type="application/rss+xml" />
	<link>http://thinkvitamin.com</link>
	<description>The Web Practitioner&#039;s Blog</description>
	<lastBuildDate>Thu, 09 Feb 2012 16:41:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Same DOM Errors, Different Browser Interpretations</title>
		<link>http://thinkvitamin.com/code/same-dom-errors-different-browser-interpretations/</link>
		<comments>http://thinkvitamin.com/code/same-dom-errors-different-browser-interpretations/#comments</comments>
		<pubDate>Fri, 06 Jun 2008 18:07:21 +0000</pubDate>
		<dc:creator>Hallvord R. M. Steen</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://www.thinkvitamin.com/features/dev/same-dom-errors-different-browser-fixes</guid>
		<description><![CDATA[Introduction In this article I will explore the DOM, look at some common kinds of errors that are found in the DOM and how different debugging tools can be used to find such DOM errors and make sure that the DOM is interpreted consistently across browsers. Along the way, I&#8217;ll introduce Opera Dragonfly, the new [...]]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>
<p>In this article I will explore the DOM, look at some common kinds of errors that are found in the DOM and how different debugging tools can be used to find such DOM errors and make sure that the DOM is interpreted consistently across browsers. Along the way, I&rsquo;ll introduce <a href="/images/articles/dragonfly/http://www.opera.com/products/dragonfly/">Opera Dragonfly</a>, the new kid on the web development debugging block, and show how it performs.</p>
<h2>What is the DOM?</h2>
<p>When a browser receives HTML code from a website, it creates a structured overview of the HTML document. This overview is known as the DOM, and through its structure JavaScript can access the various parts of the document.</p>
<p>The &ldquo;parent&rdquo; of the DOM is the <code>document</code> object, and using its methods and properties you can reach every part of the HTML file &mdash; for example by getting the first <code>div</code> with <code>document.getElementsByTagName('div')[0]</code> or the first element in the document with <code>document.firstChild</code>.</p>
<p>The DOM is usually visualised as a tree-like structure, as seen in Figure 1. The document itself should have only one child &mdash; typically the <code>html</code> element &mdash; and that element usually has the two children <code>head</code> and <code>body</code>. Each of those can have several children, so comparing this structure to the branches of a tree is a good way to understand it.</p>
<p><img src="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-dom-tree.png" alt="The DOM structure of a simple HTML document as a tree" /></p>
<p class="comment">Figure 1: The DOM structure of a simple HTML document, as viewed in the DOM viewer of Opera Dragonfly as a tree structure.</p>
<p>When constructing the DOM, the quality of the markup is very important. If the markup is not valid &mdash; for example if elements are not closed correctly &mdash; it&rsquo;s much harder to create a tree structure from it. If, say, a document contains the markup <code>&lt;html&gt;&lt;head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;</code> &mdash; what is the browser going to do? Make <code>body</code> a child of <code>head</code>? Since the <code>head</code> contents are not visible in user agents, this might make the entire document disappear!</p>
<p>Because invalid markup is so common, browsers have to add lots of special rules for creating DOM structures from invalid markup. These rules differ somewhat between browsers, which means that using invalid markup dramatically increases the risk that your site will appear differently in different browsers &mdash; or even break completely in some of them.</p>
<h2>Common markup / DOM errors</h2>
<p>Below I will look at some commonly encountered DOM errors, and how browsers interpret the markup.</p>
<h3>Bad closing and nesting of elements</h3>
<p>If you look at the first example file &mdash; <a href="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-unclosed-b.htm" alt="invalid HTML example unclosed">df-dom-demo-unclosed-b.htm</a> &mdash; you will see that the markup is invalid &mdash; there are multiple problems with it, in terms of unclosed elements and incorrect nesting. If you look at the generated DOM in various web page debugger tools (see Figure 2), you will see that browsers interpret this HTML very differently.</p>
<p><img src="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-unclosed-b-dragonfly.png" alt="example invalid dom interpreted by Opera Dragonfly" /><br />
<img src="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-unclosed-b-firebug.png" alt="example invalid dom interpreted by firebug" /><br />
<img src="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-unclosed-b-IE-dev-toolbar.png" alt="example invalid dom interpreted by IE developer toolbar" /></p>
<p class="comment">Figure 2: From top to bottom, this shows our incorrectly closed/nested example DOM as represented in Opera Dragonfly, Mozilla Firebug, and the Internet Explorer developer toolbar.</p>
<p>The DOM inspectors reveal that these browsers handle markup errors in very different ways: Opera makes the subsequent elements children of the <code>b</code> that lacks a closing tag. Firefox adds extra <code>b</code> elements <em>between</em> the <code>p</code> tags that were not present in the markup. In IE&rsquo;s DOM we see that the text &ldquo;This text should be a link&rdquo; in fact appears to be outside the <code>a</code> tag that creates the link.</p>
<p>Because there is no standard way to handle invalid markup, none of these browsers are doing anything particularly wrong here. However, if you start adding extra styling like <code>display:none</code> to any of these elements or try cloning and manipulating them through the DOM, you&rsquo; get unexpected results across browsers because of the way the invalid markup is parsed into different DOM structures.</p>
<h3><code>body</code> inside the <code>head</code></h3>
<p>In the second sample file &mdash; <a href="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-head-contents.htm" alt="invalid HTML example head content">df-dom-demo-head-contents.htm</a> &mdash; you can see another example of invalid markup. There is a <code>div</code> element inside the <code>head</code> section. Check out this demo in various DOM explorers and you will see that all browsers move the <code>div</code> element out of the <code>head</code> and into the <code>body</code>. Figure 3 shows the different ways in which this DOM is interpreted by different browsers:</p>
<p><img src="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-markup-in-head-dragonfly.png" alt="example invalid dom interpreted by Opera Dragonfly" /><br />
<img src="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-markup-in-head-firebug.png" alt="example invalid dom interpreted by firebug" /><br />
<img src="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-markup-in-head-IE-dev-toolbar.png" alt="example invalid dom interpreted by IE developer toolbar" /></p>
<p class="comment">Figure 3: From top to bottom, this shows our content in the head example&rsquo;s DOM as represented in Opera Dragonfly, Mozilla Firebug, and the Internet Explorer developer toolbar.</p>
<p>In Opera and IE, this means that any <code>head</code> content after the <code>div</code> also is moved outside of the <code>head</code> section. Also note the way Firefox has moved the <code>style</code> element from the body into the head. <code>style</code> elements are not allowed inside the <code>body</code> of course, so this is a logical thing to do, but it might confuse your script if it goes looking for the <code>style</code> element in a certain place in the tree.</p>
<h2>Using DOM inspectors for debugging</h2>
<p>As you have seen above, using DOM inspectors is a great way to <strong>see how browsers interpret the markup</strong>. This view can help explain issues you may run into when using the DOM via a JavaScript application. Some of the following examples are rather advanced, and it helps to have several of the DOM inspectors mentioned installed so that you can test the demos by yourself. The DOM inspectors used for the below analysis are Opera Dragonfly, Mozilla Firebug, the Webkit (Safari) Web Inspector, and the IE Web Developer Toolbar.</p>
<p>The third example file &mdash; <a href="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-app-meta.htm" alt="example file for cross browser DOM debugging">df-dom-demo-app-meta.htm</a> &mdash; is created by a rather unlucky web developer who has made several assumptions about how the DOM works. It turns out that he is wrong on most counts, and the app causes issues in most browsers! To start with, it doesn&#8217;t include a proper doctype in the first line. It then goes on to include a custom <code>test</code> element and a <code>meta</code> element with a custom <code>http-equiv</code> attribute value inside the <code>head</code>. Lastly, it includes a script inside the <code>body</code> that tries to read attribute values from both the <code>meta</code> and the <code>test</code> elements.</p>
<ul>
<li>
<p>In Opera it generates two exceptions. Using the Opera Dragonfly DOM explorer (see Figure 4) you can see that the reason is that the <code>test</code> and <code>meta</code> elements are not inside the <code>head</code>. When Opera sees the <code>test</code> element, it thinks the custom element name indicates the page content start, so it closes the <code>head</code> section and traps both elements outside it.</p>
<p><img src="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-app-meta-dragonfly.png" alt="the debugging example in dragonfly" /></p>
<p class="comment">Figure 4: Opera Dragonfly shows that Opera has trapped the two rogue elements outside the <code>head</code>. Hence, when the script looks for them inside the <code>head</code> section it can&#8217;t find them and throws exceptions.</p>
</li>
<li>
<p>In Firefox (see Figure 5), you will get the odd output message &ldquo;name of bar attribute is _moz-userdefined&rdquo; and sure enough, with Firebug&#8217;s DOM explorer you will see that Firefox added a <code>_moz-userdefined</code> attribute to the <code>test</code> element.</p>
<p><img src="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-app-meta-firebug.png" alt="the debugging example in firebug" /></p>
<p class="comment">Figure 5: Firebug shows that Firefox has returned an error message and added an attribute to mark the <code>test</code> element as undefined in HTML. Since the script reads the first attribute from the element, it sees the <code>_moz-userdefined</code> attribute instead of what we expected.</p>
</li>
<li>
<p>In WebKit you get one exception (see Figure 6). Like Opera, it moves the <code>test</code> element out of <code>head</code>. Unlike Opera, it appends the element to <code>body</code>, and it doesn&#8217;t move the <code>meta</code> element.</p>
<p><img src="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-markup-in-head-webkit-inspector.png" alt="the debugging example in webkit" /></p>
<p class="comment">Figure 6: WebKit shows that Safari has moved the <code>test</code> element into the <code>body</code>.</p>
</li>
<li>
<p>In IE7 the output is &ldquo;Name of bar attribute is language. Value of meta attribute is null&rdquo; &mdash; there are no exceptions reported, and neither result is what was expected. The IE Developer Toolbar&#8217;s DOM view is not quite powerful enough to explain these results &mdash; there are two IE bugs at play here: one is that IE exposes internal generic attributes in the <code>Element.attributes</code> collection, second is that weirdly enough the <code>meta http-equiv</code> attribute simply disappears. See Figure 7 for the output in the IE web developer toolbar.</p>
<p><img src="http://thinkvitamin.com/images/articles/dragonfly/df-dom-demo-app-meta-IE-dev-toolbar.png" alt="the debugging example in the IE web developer toolbar" /></p>
<p class="comment">Figure 7: The IE web developer toolbar does not quite show us the DOM the scripts are working on. It appears to show that IE has preserved the <code>meta http-equiv</code> attribute, yet when we try reading it with the DOM method getAttribute() we get nothing.</p>
</li>
</ul>
<h2>Summary</h2>
<p>Our unlucky developer has a few things to fix to get this example working properly cross-browser, but in this example it&rsquo;s not hard to do so. He&rsquo;ll need to validate the markup, get rid of the custom elements (and avoid these in the future, particularly inside the <code>head</code> as browsers are very picky about what they allow to appear there), and not rely on attribute order when reading attributes. You can see from the examples shown above that valid code is perhaps the most important factor for cross-browser compatibility on the DOM level, and that DOM inspectors help you understand how your scripts can access the document and how the markup is interpreted.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkvitamin.com/code/same-dom-errors-different-browser-interpretations/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.357 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-11 18:26:12 -->

