Manipulating the DOM with javascript – part 2 of 4

In my last post, I explored the createElement function to begin showing you how to add, remove and replace elements in your HTML pages with javascript. In this post, I will explore the appendChild and insertBefore functions. These are two of the three functions you will use to actually insert the new element you created in the last post.

appendChild

The first insert function we’ll look at is appendChild. By definition, appendChild simply places the element wherever inside the “parent” element that there is room. In reality, it actually adds the element at the very end of the parent element.

The appendChild function requires two pieces of information. First, it needs a reference to the element into which we intend to append this element. Next, it needs a reference to the element we intend to insert. Therefore, to use this function, we will need to locate the element into which we want to insert this image. In the grand scheme of things, this element is referred to as our “parent” element. The easiest way to do this is to locate the element according to its id. Let’s say, for example, that we want to add the image to a div within our page. If we were smart, we’ve already assigned an ID to this div. The div definition might look something like:

<div id="mydiv">This is some text within my div.</div>

Now, we need to use our javascript to locate that element. We will do that by using the getElementById function (another DOM function that’s available in most XML-compatible languages). In this case, we need to write our code like this:

var mydiv = document.getElementById('mydiv');

In javascript, the keyword “document” refers to the root element in our XHTML file. It is automatically assigned when the script is instantiated. If we were using another programming language, we might need to use a slightly different structure, such as: doc = xml.documentElement (where “xml” is a file system object assigned to the document we are manipulating).

Now, we are ready to insert our image at the end of our div. We do so with the following code:

mydiv.appendChild(myimg);

With that code, the image we created (and stored into the variable “myimg”) has now been added to our div. If we had the ability to view the source of our file after the javascript was executed, it would now look like:

<div id="mydiv">This is some text within my div.<img src="test.gif" alt="This is a test" id="myimg"></div>

For some strange reason, when using these functions to insert an img tag (or any self-terminating tag, for that matter), the DOM does not close the tag the way it should, but I have not yet encountered any instances where that’s been a problem.

Moving on, though, you can see that our image was “appended” onto the end of our parent element (in this case, the div with the ID of “mydiv”, which we stored into the variable “mydiv”).

insertBefore

We will now take a quick look at the insertBefore function. Once again, this function does exactly what it sounds like it will do. It inserts an element before another element in the DOM. The insertBefore function requires three pieces of information. Just like the appendChild function, it requires a reference to our “parent object” (in this case, mydiv) and a reference to our new element (in this case, myimg). However, this function also requires a reference to one more element in the DOM. That is the element that you want to move out of the way to make room for your new element. In other words, we need to find an element that will become the “sibling” of our new element once it’s inserted.

We can do this by walking the DOM tree. That will normally work just fine if you want to insert the element at the top of your parent element. However, if you are trying to insert the new element in a specific place inside of the parent element (let’s say there are three images already inside of the parent, and you want to insert this new image just before the third image, pushing the old image into the fourth place, and making your new image the third image inside of the div). This can be troublesome if you attempt to walk the DOM tree, simply because different browsers interpret the tree slightly differently.

In Firefox, spaces are ignored within the DOM. However, in Internet Explorer, spaces are considered “textNodes”, and are added in as a separate entry within the DOM. Therefore, if your code looks like:

<div id="mydiv">
<img src="img1.gif" alt="First Image" />
<img src="img2.gif" alt="Second Image" />
<img src="img3.gig" alt="Third Image" />
</div>

Internet Explorer will interpret the DOM in the following way:

  1. div (id=mydiv)
    1. textNode (that’s your hard return in your code)
    2. img
    3. textNode
    4. img
    5. textNode
    6. img
    7. textNode

However, Firefox will interpret the DOM this way:

  1. div (id=mydiv)
    1. img
    2. img
    3. img

You should be able to see the problem with walking the DOM tree from that example. In Firefox, your third image will be the third child element of “mydiv”. However, in Internet Explorer, your third image will be the sixth child element of “mydiv”. So, how do you know how far to walk the DOM tree? It’s a difficult proposition. That’s why IDs are so important.

Of course, you could walk the DOM and inspect the elements to see if they are images or not, but that becomes increasingly difficult, depending on the amount of code you have inside of your div.

Now, getting back on track, we can use the following code to insert the new image at the very beginning of our div:

mydiv.insertBefore(myimg,mydiv.firstChild);

That will result in our div looking like:

<div id="mydiv"><img src="test.gif" alt="This is a test" id="myimg">
<img src="img1.gif" alt="First Image" />
<img src="img2.gif" alt="Second Image" />
<img src="img3.gig" alt="Third Image" />
</div>

However, if we want to insert our element before the third image, rather than at the beginning of the div, we would need to have an ID assigned to our third image. For purposes of this example, let’s say that our third image has an ID of “img3”. Then, our code would look like:

mydiv.insertBefore(myimg,document.getElementById('img3'));

Again, we could try inserting the new element just before the “lastChild” in our div, but that could be problematic if our last child is interpreted as the hard return after the last image tag. If we were to try that, it would look like:

mydiv.insertBefore(myimg,mydiv.lastChild);

In my next post, we will explore the “replaceChild” and the “removeChild” functions.

2 Responses