Introduction to the Document Object Model
Review the W3C DOM2 standard recommendation.The first step is to create a node object of the type you want using one
of document.createElement(), document.createAttribute()
or
document.createTextNode().
For attributes, however, you'll
probably just want to create an element node and assign it attributes directly
(recall that IE, as of version 5.5, doesn't support
createAttribute()
).
Working with Text Nodes
Let's start with a text node. Below is some sample code showing how to create a text node and assign it a value.
var myTextNode = document.createTextNode("my text");
Now you have a text node. But it's not part of the document tree. To make it appear on the page, you need to add it as a child to an existing node within the tree. Since text nodes cannot have children, you can't attach it to another text node. Attributes nodes are not part of the document tree, so you don't want to attach it to one of them. That leaves element nodes.
Since element nodes can several children, there are a few different methods provided that allow you to specify where to add the new node among its existing children. These are best illustrated by example.
Here, the appendChild()
method is used to add new text to a
paragraph element. It also allows you to remove the last node added using the
removeChild()
method:
Initial text within a paragraph element.
Add Text Node | Remove Text Node
Now take a look at the code:
<p id="sample1">Initial text within a paragraph element.</p> ... code to add a text node ... var text = document.createTextNode(" new text " + (++counter1)); var el = document.getElementById("sample1"); el.appendChild(text); ... code to remove the last child node ... var el = document.getElementById("sample1"); if (el.hasChildNodes()) el.removeChild(el.lastChild);
Adding text is easy, the code creates a new text node, locates the paragraph
element node and calls appendChild()
to insert it at the end of
it's childNodes
array. A global counter variable is used on the
text itself so you can distinguish each new node in the browser display.
Removing text is almost as easy, using a call to
removeChildNode()
. The only difference in the addition of a
reference node, to indicate which of the element's children is to be removed.
Here we use the element's lastChild
property which always points
to the last node of the element's childNodes
array. Note that it
will even remove the initial text hard coded in the P tag if that is the only
child.
Also note the use of the hasChildNodes()
method which simply
returns true
or false
to indicate if the given node
currently has any children. Here it's used to prevent an error by calling
removeChild
when there are no children left.
Normalizing and Splitting Text Nodes
In the above example, the new text nodes are added as independent children. But if you had hard coded additional text in the HTML,
<p id="sample1">Initial text within a paragraph element. new text 1 new text 2 new text 3</p>
it would appear in the DOM as a single child text node of the paragraph element. In other words, the node tree produced by dynamically adding content may appear different from the node tree that would result if that content had been included in the static HTML code.
This may or may not be desirable depending on what you're trying to do. In some cases you may want combine text nodes to make the tree reflect what it would if the new, dynamically added content had been part of the original, static HTML code.
The normalize()
method provides this functionality. Calling it
on an element will "clean up" the node tree, combining any adjacent text nodes
and removing any empty ones.
normalize
method. The
example below will not work properly on this browser. IE 6.0, however, does
appear to support it although the current beta version is buggy.
To demonstrate, here's the same example used above but with additional links provided to normalize the paragraph element and show it's current number of children.
Initial text within a paragraph element.
Add Text Node | Remove Text Node | Show Child Node Count | Normalize Element
You can see that as you add text, the number of child nodes increases but any time you normalize the paragraph, they are combined into a single text node. Here's the code for the additional links:
... normalize element ... el = document.getElementById("sample2"); el.normalize(); ... show number of child nodes ... el = document.getElementById("sample2"); alert(el.childNodes.length);
Conversely, you can split a single text node into two separate ones using
the splitText()
method This can be useful if you want to
dynamically alter a single word or phrase or insert an element in a line of
text.
Let's set up another example. This time, the remove link will delete the first child of the paragraph. Initially, this will be the entire sentence. But if you use the separate link first, it will split off the first word in the text and a subsequent remove will delete only that word. The reset link allows you to start over.
Initial text within a paragraph element.
Separate First Word | Remove First Text Node | Reset
And here's the code for each function:
... split at first word ... el = document.getElementById("sample3"); if (el.hasChildNodes()) { text = el.firstChild; i = text.nodeValue.indexOf(" "); if (i >= 0) text.splitText(i + 1); } ... remove first text node ... el = document.getElementById("sample3"); if (el.hasChildNodes()) el.removeChild(el.firstChild); ... reset the example ... el = document.getElementById("sample3"); while (el.hasChildNodes()) el.removeChild(el.firstChild); text = document.createTextNode( "Initial text within a paragraph element."); el.appendChild(text);
A couple of notes here. The nodeValue
of a text node is simply
a string. The splitText()
method expects an offset value to tell
it where to split the text. The string indexOf()
method is used to
find the offset of the first space in the text and pass it on to
splitText().
Second, the reset code simply deletes all child nodes of the paragraph and then adds the original text back as a single node.