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’ll introduce Opera Dragonfly, the new kid on the web development debugging block, and show how it performs.
What is the DOM?
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.
The “parent” of the DOM is the document
object, and using its methods and properties you can reach every part of the HTML file — for example by getting the first div
with document.getElementsByTagName('div')[0]
or the first element in the document with document.firstChild
.
The DOM is usually visualised as a tree-like structure, as seen in Figure 1. The document itself should have only one child — typically the html
element — and that element usually has the two children head
and body
. Each of those can have several children, so comparing this structure to the branches of a tree is a good way to understand it.
Figure 1: The DOM structure of a simple HTML document, as viewed in the DOM viewer of Opera Dragonfly as a tree structure.
When constructing the DOM, the quality of the markup is very important. If the markup is not valid — for example if elements are not closed correctly — it’s much harder to create a tree structure from it. If, say, a document contains the markup <html><head><body></body></html>
— what is the browser going to do? Make body
a child of head
? Since the head
contents are not visible in user agents, this might make the entire document disappear!
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 — or even break completely in some of them.
Common markup / DOM errors
Below I will look at some commonly encountered DOM errors, and how browsers interpret the markup.
Bad closing and nesting of elements
If you look at the first example file — df-dom-demo-unclosed-b.htm — you will see that the markup is invalid — 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.
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.
The DOM inspectors reveal that these browsers handle markup errors in very different ways: Opera makes the subsequent elements children of the b
that lacks a closing tag. Firefox adds extra b
elements between the p
tags that were not present in the markup. In IE’s DOM we see that the text “This text should be a link” in fact appears to be outside the a
tag that creates the link.
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 display:none
to any of these elements or try cloning and manipulating them through the DOM, you’ get unexpected results across browsers because of the way the invalid markup is parsed into different DOM structures.
body
inside the head
In the second sample file — df-dom-demo-head-contents.htm — you can see another example of invalid markup. There is a div
element inside the head
section. Check out this demo in various DOM explorers and you will see that all browsers move the div
element out of the head
and into the body
. Figure 3 shows the different ways in which this DOM is interpreted by different browsers:
Figure 3: From top to bottom, this shows our content in the head example’s DOM as represented in Opera Dragonfly, Mozilla Firebug, and the Internet Explorer developer toolbar.
In Opera and IE, this means that any head
content after the div
also is moved outside of the head
section. Also note the way Firefox has moved the style
element from the body into the head. style
elements are not allowed inside the body
of course, so this is a logical thing to do, but it might confuse your script if it goes looking for the style
element in a certain place in the tree.
Using DOM inspectors for debugging
As you have seen above, using DOM inspectors is a great way to see how browsers interpret the markup. 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.
The third example file — df-dom-demo-app-meta.htm — 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’t include a proper doctype in the first line. It then goes on to include a custom test
element and a meta
element with a custom http-equiv
attribute value inside the head
. Lastly, it includes a script inside the body
that tries to read attribute values from both the meta
and the test
elements.
-
In Opera it generates two exceptions. Using the Opera Dragonfly DOM explorer (see Figure 4) you can see that the reason is that the
test
andmeta
elements are not inside thehead
. When Opera sees thetest
element, it thinks the custom element name indicates the page content start, so it closes thehead
section and traps both elements outside it.Figure 4: Opera Dragonfly shows that Opera has trapped the two rogue elements outside the
head
. Hence, when the script looks for them inside thehead
section it can’t find them and throws exceptions. -
In Firefox (see Figure 5), you will get the odd output message “name of bar attribute is _moz-userdefined” and sure enough, with Firebug’s DOM explorer you will see that Firefox added a
_moz-userdefined
attribute to thetest
element.Figure 5: Firebug shows that Firefox has returned an error message and added an attribute to mark the
test
element as undefined in HTML. Since the script reads the first attribute from the element, it sees the_moz-userdefined
attribute instead of what we expected. -
In WebKit you get one exception (see Figure 6). Like Opera, it moves the
test
element out ofhead
. Unlike Opera, it appends the element tobody
, and it doesn’t move themeta
element.Figure 6: WebKit shows that Safari has moved the
test
element into thebody
. -
In IE7 the output is “Name of bar attribute is language. Value of meta attribute is null” — there are no exceptions reported, and neither result is what was expected. The IE Developer Toolbar’s DOM view is not quite powerful enough to explain these results — there are two IE bugs at play here: one is that IE exposes internal generic attributes in the
Element.attributes
collection, second is that weirdly enough themeta http-equiv
attribute simply disappears. See Figure 7 for the output in the IE web developer toolbar.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
meta http-equiv
attribute, yet when we try reading it with the DOM method getAttribute() we get nothing.
Summary
Our unlucky developer has a few things to fix to get this example working properly cross-browser, but in this example it’s not hard to do so. He’ll need to validate the markup, get rid of the custom elements (and avoid these in the future, particularly inside the head
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.
Can you re-upload the broken image?
Greetings!
I reviewed this articles, and seems that i cant find out why NEWEST opera wont display my inrow, even display:block styled css links, but it displays inline links in body area also.
THIS IS THE CODE URL: http://www.p-portal.org/index.html -html 4.01 with DOCTYPE!