This tutorial is for Dojo 1.6 and may be out of date.
Up to date tutorials are available.
Dojo DOM Functions
In this tutorial, you'll learn about how to use Dojo to manipulate the DOM in a simple, cross-browser way. Using basic DOM knowledge and only a few Dojo functions, you will be able to efficiently create, read, update and delete elements in the page on the fly.
Getting Started
As far as browser-based JavaScript is concerned, the Document Object Model (DOM) is the glass that we paint on to put content and user interface in front of our users. If we want to augment, replace or add to the HTML once loaded into the browser, JavaScript and the DOM is how it's done. Dojo aims to make working with the DOM easy and efficient by providing a handful of convenience functions that fill some awkward cross-browser incompatibilities and make common operations simpler and less verbose.
To explore those functions we will be manipulating a simple page containing an unordered list with five elements in it:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Demo: DOM Functions</title> <script src="//ajax.googleapis.com/ajax/libs/dojo/1.6.3/dojo/dojo.xd.js"></script> <script> dojo.ready(function(){ // "ready" entry point }); </script> </head> <body> <ul id="list"> <li id="one">One</li> <li id="two">Two</li> <li id="three">Three</li> <li id="four">Four</li> <li id="five">Five</li> </ul> </body> </html>
The page already has the Dojo script tag, and you should recognize the dojo.ready
block. All code that manipulates the DOM must wait until the DOM is ready before it can be executed.
Retrieval
First things first: We need to know how to get elements from the DOM, in order to work with them. The easiest way to do that is with dojo.byId
. When you pass the ID of the element you'd like to access to dojo.byId
, you will receive a DOM node object if a node is found with that ID, and a null value if no matching node is found.
This is the equivalent of using document.getElementById
, but with two advantages: it is shorter to type, and it works around some browsers' buggy implementation of getElementById
. Another nice feature of dojo.byId
is that when it is passed a DOM node, it immediately returns that node. This helps to create APIs that take both strings and DOM nodes. Let's look at an example:
function setText(node, text){ node = dojo.byId(node); node.innerHTML = text; } dojo.ready(function(){ var one = dojo.byId("one"); setText(one, "One has been set"); setText("two", "Two has been set as well"); });View Demo
The setText
function sets the text of a node, but since it passes the node
argument to dojo.byId
it will take either a node ID as a string or a DOM node.
Creation
Another thing you will be doing often is creating elements. Dojo doesn't prevent you from using the native document.createElement
method to create elements, but creating the element and setting all the necessary attributes and properties on it can be verbose.
Furthermore, there are enough cross-browser quirks to attribute setting to make dojo.create
a more convenient and reliable option.
The arguments to dojo.create
are as follows: node name as a string, properties of the node as an object, an optional parent or sibling node, and an optional position in reference to the parent or sibling node (which defaults to "last").
It returns the new DOM element node. Let's take a look at an example:
dojo.ready(function(){ var list = dojo.byId("list"), three = dojo.byId("three"); dojo.create("li", { innerHTML: "Six" }, list); dojo.create("li", { innerHTML: "Seven", className: "seven", style: { fontWeight: "bold" } }, list); dojo.create("li", { innerHTML: "Three and a half" }, three, "after"); });View Demo
A simple list item is created with the content of "Six" and appended to the list. Next, another list item is created with the content of "Seven", its className
property is set to "seven", it's styled so it has a bold font, and then appended to the list. Finally, a list item is created with the contents "Three and a half" and is inserted after the list item with the ID "three".
When would you create elements explicitly like this, versus setting a container element's innerHTML
property? If you already have your content as a string of HTML, setting the innerHTML
property will always be faster. However, dojo.create
comes into its own when you want to create elements but not immediately place them in the DOM, or when you want to insert or append a new element without disturbing the sibling nodes around it.
Placement
If you already have a node and want to place that node, you will need to use dojo.place
. The arguments are as follows: a DOM node or string ID of a node to place, a DOM node or string ID of a node to use as a reference, and an optional position as a string which defaults to "last" if not provided. This is very similar to what we saw in dojo.create
and, in fact, dojo.create
uses dojo.place
under the hood. For our example, we have added a few buttons to the page:
<button onclick="moveFirst();">The first item</button> <button onclick="moveBeforeTwo();">Before Two</button> <button onclick="moveAfterFour();">After Four</button> <button onclick="moveLast();">The last item</button>
The example defines functions which move the third node around the list using dojo.place
:
function moveFirst(){ var list = dojo.byId("list"), three = dojo.byId("three"); dojo.place(three, list, "first"); } function moveBeforeTwo(){ var two = dojo.byId("two"), three = dojo.byId("three"); dojo.place(three, two, "before"); } function moveAfterFour(){ var four = dojo.byId("four"), three = dojo.byId("three"); dojo.place(three, four, "after"); } function moveLast(){ var list = dojo.byId("list"), three = dojo.byId("three"); dojo.place(three, list); }View Demo
The possible values for the placement argument are "before", "after", "replace", "only", "first", and "last". Please see the reference guide for dojo.place for more details as to what each placement option does, though the names are decently intuitive.
In the simple case, dojo.place does little more than the native parentNode.appendChild(node)
might do. Its value is in being able to easily specify position, whether it is in reference to a parent or sibling node - with one consistent API.
Destruction
Most often you'll be creating nodes, but occasionally, you'll want to remove nodes as well. There are two ways to do this in Dojo: dojo.destroy
which will destroy a node and all of its children, while dojo.empty
will only destroy the children of a given node. Both take a DOM node or a string ID of a node as their only argument. We're going to add two more buttons to our page:
<button onclick="destroyFirst();">Destroy the first list item</button> <button onclick="destroyAll();">Destroy all list items</button>
function destroyFirst(){ var list = dojo.byId("list"), items = list.getElementsByTagName("li"); if(items.length){ dojo.destroy(items[0]); } } function destroyAll(){ dojo.empty("list"); }View Demo
The first button will destroy the first item in the list on each click. The second empties the list entirely.
Conclusion
So far, we have a pretty comprehensive set of tools that we can use to do simple DOM manipulation, from creating nodes, to moving them about, to getting rid of them -- but they all work on only one node at a time. What if the nodes you want to work with don't have IDs? The next tutorial will cover dojo.query
, which allows us to search for and work with nodes based on CSS selectors!