Fun With The DOM

Here's an index.pug for the sort of web project I've been going on about for a while:

html  
    head
        title Fun With The DOM
    body
        h1 Fun With The DOM
    script(src='js/main.js')

This gets transformed into a web page with the following HTML:

<html>  
    <head>
        <title>Fun With The DOM</title>
    </head>
    <body>
        <h1>Fun With The DOM</h1>
    </body>
    <script src="js/main.js"></script>
</html>  

When a browser renders that HTML file, it creates an object that models the document, called a document object model or DOM for short. For example, the DOM for this page will have a body object, and an h1 object that contains the text "Fun With The DOM"

We, as developers, can use JavaScript to interact with the DOM to query, modify, or add behaviors to our web pages.

For example, if I wanted to get the contents of the h1 element I'd write the following in main.js:

console.log(document.querySelector('h1').innerHTML)  

Which would display:

Fun With The DOM  

to the web console of your choice.

Let's say I had two paragraph elements:

p I like to snuggle with cute goat babies  
p Goat babies are sooo cute  

If I wanted to grab both of them I could do the following:

document.querySelectorAll('p')  

But what if I only want one of them? I can add an id to one, which will let me grab only the paragraph element with the id I specify:

p I like to snuggle with cute goat babies  
p(id='cute-goats') Goat babies are sooo cute  
document.querySelector('#cute-goats')  

Those of you that know a bit of CSS will recognize the # character as indicating an id.

We can also select by class:

p(class='goat-paragraph') I like to snuggle with cute goat babies  
p(class='goat-paragraph') Goat babies are sooo cute  
p(class='robot-paragraph') The robots are after your job!  
var R = require('ramda')

R.map(  
    R.prop('innerHTML'),
    document.querySelectorAll('.goat-paragraph'))

/*returns [
    "I like to snuggle with cute goat babies",
    "Goat babies are sooo cute"
]*/

Just like # indicates id, . indicates class.

Let's say we wanted to add a class to a list of elements:

R.map(  
    p => p.classList.add('silly-paragraph'),
    document.querySelectorAll('.goat-paragraph'))

You can also remove classes with classList.remove, get a list of any of an element's attributes by simply grabbing its attributes property.

If you'd like to dynamically modify the contents of a page, here's one way to do it:

document  
    .querySelector('body')
    .innerHTML =
        '<p>stuff</p><p>things</p>'

I'd say there are limits to this. I don't think this is the way to build large single-page-applications. Eventually it becomes a better idea to start using a templating library like Mustache.js or web frameworks like Angular or React

In any event, I think learning how to directly manipulate the DOM is useful, even if you plan to use web frameworks most of the time.

What about doing things when a user clicks a button? Here's a way to add that behavior to a web page:

html  
    head
        title Fun With The Dom
    body
        h1(id='message') You haven't clicked it yet
        button(id='clickit') click it
    script(src='js/main.js')
document.querySelector('#clickit').onclick =  
    () =>
        document.querySelector('#message').innerHTML =
            'You clicked it!'

I recommend checking out the Mozilla Developer Network's page about DOM elements as well as their page on event handlers to get a full list of what's available.

Another site worth checking out is You Might Not Need JQuery.

JQuery is a useful library for querying and manipulating the DOM (as well as a few other things). It's been pretty popular, so popular that a lot of developers don't know much about the browser's native ability to query and manipulate the DOM.

Recently though, there's been some movement away from using JQuery (at least using it exclusively) in favor of more structured frameworks (again, like React and Angular :) ).

By all means, check out JQuery, but I think (with this blog) I'll just skip to the good stuff and write posts about React. :)

Looking for a software developer?