Arieh.co.il

Javascript Guide - The DOM

You can now also navigate the guide through the table of contents.

So - you want to learn how to make your website interactive? Well, after a few other posts, it is time we learn how to play with the DOM.

the Document Object Model

The Document Object Model (DOM) is a cross-platform and language-independent convention for representing and interacting with objects in HTML, XHTML and XML documents

Wikipedia

In javascript, there is a designated accessor to all of the DOM's API- the document object. The document object holds a reference to the root element of our document - the html tag, and also a long list of designated methods for manipulating the page.

Unfortunately, the DOM sucks. Although it holds great potential, at it's core, the DOM is awkward and bulky. In fact, this is why libraries like JQuery got their fame. But, in order to use JS you should at least be familiar with it.

So here follows a brief introduction to the DOM, and how we use it.

How does it work?

At it's core, the DOM is a tree-like representation of our page. Each element is a node. Every element contains references to It's parent and it's neighboring siblings, and an array of it's child elements.

The best way for you to see a representation of the DOM tree is for you to open the HTML tab in firebug.

Creating an Element

Element creating is done via the document.createElement method, and it receives 1 argument - the tag name:

    var div = document.createElement('div');
    console.log(div);
    
run code

If we want to set attributes to our element, we do it via the element.setAttribute method:

    div.setAttribute('id','some-id');
    console.log(div);
    
run code

And if we want to access an attribute - element.getAttribute:

    console.log(div.getAttribute('id'));
    
run code

So far so good - although the names are long (which means easier to misspell), they are meaningful and quite easy to remember. But what can we do with that element?

Well, for that we need to inject it. But first, we need to select a target. The best and fastest way is to use document.getElementById. This method receives one argument - an existing id from our page, and returns the element with that ID.

Now, we use the element.appendChild method to inject our newly created element. Below is an empty box with the id of example1.

    var ex1 = document.getElementById('example1');
    ex1.appendChild(div);
    
run code

note - I've set a style to some-id so you can see it injected

So this wasn't too hard was it? well, what about adding some text to it? Well, there are two ways - the DOM way, and the hacky way.

  1. The right way - document.createTextNode

    You see - in the DOM, everything is a node. Text is no exception. So when we want to add text to our element, we first need to create a text node, and then append it to our element:

                var  div  = document.createElement('div')
                    , text = document.createTextNode('i am just some random text');
                
                div.appendChild(text);
                
                //notice that i used a nice aspect of the DOM - chaining - all methods of the DOM return a node, 
                //so i can chain multiple methods one after the other:
                document.getElementById('example2').appendChild(div);
                
    run code
  2. The easy way - innerHTML

    innerHTML is a string representation of our element's inner html. As it is a string, we can do all stringy stuff to it, like assignment and concatenation. For quick operation, it is quite useful, and much faster than normal DOM manipulations.

                var  div  = document.createElement('div');
                div.innerHTML = "im created using the easier method!";
                document.getElementById('example3').appendChild(div);
                
    run code

    And if that wasn't enough - there is more - we can use it to nest elements - by simply writing their HTML:

                var  div  = document.createElement('div');
                div.innerHTML = "<strong>im created using the easier method!</strong>";
                document.getElementById('example4').appendChild(div);
                
    run code

Now, you might ask yourself - why ever use the first way? why use any of this if we can simply write html? Well, there are a few answers to that question:

Traversing The DOM

As mentioned before, every node holds 3 pointers - one to it's parent, one to it's previous element, and one to it's next. For this example, we will use the following list. It's second element's ID is li-2.

  1. I'm 1
  2. I'm 2
  3. I'm 3
        var li = document.getElementById('li-2');
        
        console.log('parent:',   li.parentNode);
        console.log('previous:', li.previousSibling);
        console.log('next:',      li.nextSibling);
    
run code

Lastly, to wrap up our traversal tools (yes - at it's core we get only 4...) - we have childNodes, which, as it name (might) imply, holds an array of all the elements children:

    console.log(document.getElementById('li-example').childNodes);
    
run code

Now, if you looked at your console, you might have noticed something quite annoying - since text is also a node, most of the time, the next and previous siblings of an element (at least in a well styled document) are whitespaces. Remember when I said the DM was crap?

One last thing - removing an element -

     var div = document.getElementById('example5')
        , strong = document.getElementById('str1');
        
     div.removeChild(strong);
    
run code
Im not very important. I'll be fine with you removing me... really!

We now know everything there is to know about the DOM.

Well... OK. So you might want to play with you element's styles.

Styling via the DOM

Well, there are 2 stages for playing with styles - setting a style and retrieving it. Retrieving, is actually very not straight forward, and the best I can do is to point you to an external reference. But for setting them, it's much much simpler.

Every element has a style property, which contains an array of all the styles possible. All styles names are camelCased (so, for example, margin-top becomes marginTop). The style property is linked to the element's style attributes. This means that once a style is set on that attribute, it is accessible through the property, and that once setting a style, it will appear in the style attribute.

Confused? Example to the rescue!

For this example we will use the following element:

<div id='example6' style="border:1px solid; background:#fca; width:100px; height:100px;"></div>

note - as with js - i highly encourage you not to use inline styling. this one is just used for making a point.

    var div = document.getElementById('example6');
    
    console.log(div.style.borderColor);
    
    div.style.backgroundColor = '#cae';
    
run code

Now, you might have noticed that the color was returned as an rgb string. Not very useful? too bad.

So, with all the above tools, we've learned a few things:

  1. The DOM sucks. Although it is quite a useful concept, it's implementation sucks, and I highly encourage you, once we are done with our guide (not too far away now - 2-3 more posts) that you do ahead and find yourself a nice framework to work with (more on that later on).
  2. If that wasn't enough to convince you, I will point that the DOM is not cross-browser. I've only touched basic tools on this post, but if you read the link I pointed you to - you'll learn that every browser implements the DOM differently. In fact, the DOM is the number two source for cross-browser problems (CSS being the first off course).
  3. How to use the DOM to create, find and manipulate your elements.

But we're not done with the DOM yet. On the next post, we will learn about the one thing that does shine with the DOM - it's event system.

JavaScript Reference, JavaScript Guide, JavaScript API, JS API, JS Guide, JS Reference, Learn JS, JS Documentation