dojo from the ground up

67
Dojo from the ground up, Part 1: Getting started with Dojo development Joe Lennon , Lead Mobile Developer, Core International Summary: The Dojo toolkit enables web application developers to create Rich Internet Applications by offering a wide variety of features that save development time and effort. From DOM helpers and Asynchronous JavaScript and XML (Ajax) to a full-blown widget library and object-orientation features, Dojo includes virtually everything you need to build large-scale Ajax-powered web applications. If the functions you are looking for are not included in Dojo itself, it's likely that you can find them in DojoX, a repository of extensions and experimental features that are not included in the Base or Core modules of the toolkit. In this article series, learn how to develop Dojo-powered applications from the ground up, covering the basics, Dojo's great object-orientation features, and the Dijit user interface library. By the end of this series, you will be well prepared to develop Dojo applications of your own. Introducing the Dojo Toolkit Dojo was created in 2004 to make the process of developing DHTML and JavaScript web applications easier, hiding much of the cross-browser inconsistencies that are prevalent in modern web browsers. This enabled the focus to be placed on implementing functions rather than tweaking code to make it work on every browser. Dojo is owned by the Dojo foundation, which was founded in 2005 by Alex Russell and Dylan Schiemann. Dojo is open source software (OSS) and is available under a dual-license (you can pick which one you want to adhere to) with both the Academic Free License (AFL) and a modified BSD license available. Features at a glance The features of the Dojo Toolkit are spread into four distinct sections. This division lets developers keep the file size of the library to a minimum, ensuring that the performance of their application is not burdened by a heavy JavaScript library download. For example, if you only need Ajax support functions, you only need to include the Base package; the extensive Dijit UI components will not be included. You will learn more about how Dojo loads different modules later in this series. Base The Base package provides the foundation of the Dojo Toolkit, including functions such as DOM utility functions, CSS3 selector-based DOM querying, event handling, Ajax, basic animation, and Dojo's class-based object-oriented features. The majority of this article focuses on Base. Core The Core package includes some additional functions that are not included in Base. Generally, these features tend not to be used as heavily as the functions Base provides; hence, they are loaded separately to ease the burden on the Base package. With that said, the Core package provides some really useful components including advanced animation, drag and drop, I/O, data management, internationalization (i8n), and browser history management. The Core package is not covered in this article. Dijit The Dijit package includes Dojo's extensive UI library of widgets and components. Some examples of these widgets include dialog boxes, calendars, color palettes, tooltips, and trees. It also includes a set of form controls that provide much more functionality than the standard HTML form controls, as well as complete layout management options. The third part of this series will feature more in-depth coverage of Dijit. DojoX Dojo eXtensions (DojoX) contains various sub-projects of the toolkit. Most of the experimental features of Dojo live in DojoX, but it also contains many stable components and features. DojoX will be covered briefly in the third part of this series.

Upload: harihara-krishnan

Post on 24-Oct-2014

55 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Dojo From the Ground Up

Dojo from the ground up, Part 1: Getting started with Dojo developmentJoe Lennon, Lead Mobile Developer, Core International

Summary:  The Dojo toolkit enables web application developers to create Rich Internet Applications by offering a wide variety of features that save development time and effort. From DOM helpers and Asynchronous JavaScript and XML (Ajax) to a full-blown widget library and object-orientation features, Dojo includes virtually everything you need to build large-scale Ajax-powered web applications. If the functions you are looking for are not included in Dojo itself, it's likely that you can find them in DojoX, a repository of extensions and experimental features that are not included in the Base or Core modules of the toolkit. In this article series, learn how to develop Dojo-powered applications from the ground up, covering the basics, Dojo's great object-orientation features, and the Dijit user interface library. By the end of this series, you will be well prepared to develop Dojo applications of your own.

Introducing the Dojo Toolkit

Dojo was created in 2004 to make the process of developing DHTML and JavaScript web applications easier, hiding much of the cross-browser inconsistencies that are prevalent in modern web browsers. This enabled the focus to be placed on implementing functions rather than tweaking code to make it work on every browser. Dojo is owned by the Dojo foundation, which was founded in 2005 by Alex Russell and Dylan Schiemann. Dojo is open source software (OSS) and is available under a dual-license (you can pick which one you want to adhere to) with both the Academic Free License (AFL) and a modified BSD license available.

Features at a glance

The features of the Dojo Toolkit are spread into four distinct sections. This division lets developers keep the file size of the library to a minimum, ensuring that the performance of their application is not burdened by a heavy JavaScript library download. For example, if you only need Ajax support functions, you only need to include the Base package; the extensive Dijit UI components will not be included. You will learn more about how Dojo loads different modules later in this series.

BaseThe Base package provides the foundation of the Dojo Toolkit, including functions such as DOM utility functions, CSS3 selector-based DOM querying, event handling, Ajax, basic animation, and Dojo's class-based object-oriented features. The majority of this article focuses on Base.

CoreThe Core package includes some additional functions that are not included in Base. Generally, these features tend not to be used as heavily as the functions Base provides; hence, they are loaded separately to ease the burden on the Base package. With that said, the Core package provides some really useful components including advanced animation, drag and drop, I/O, data management, internationalization (i8n), and browser history management. The Core package is not covered in this article.

DijitThe Dijit package includes Dojo's extensive UI library of widgets and components. Some examples of these widgets include dialog boxes, calendars, color palettes, tooltips, and trees. It also includes a set of form controls that provide much more functionality than the standard HTML form controls, as well as complete layout management options. The third part of this series will feature more in-depth coverage of Dijit.

DojoXDojo eXtensions (DojoX) contains various sub-projects of the toolkit. Most of the experimental features of Dojo live in DojoX, but it also contains many stable components and features. DojoX will be covered briefly in the third part of this series.

Getting started

Enough talk about Dojo. Let's get started and actually work with the toolkit. This section explains the various ways of using Dojo in your projects, how to set up a development environment using Firefox and the Firebug plug-in, and how to write some Dojo code to make sure everything is working as expected.

Setting up Dojo

The easiest way to set up Dojo is to serve it from a Content Delivery Network (CDN), which will deliver the Dojo JavaScript files from a server near the visitor rather than from your own server. Not only does this help speed up the loading of the script, it also means that there is an increased chance that the user has already loaded the Dojo files from another website, which will lead to them being loaded from cache, speeding things up even further.

In this series, it is assumed that you are using Dojo 1.5, although any 1.x version should be compatible. Including the following <script> tag in your HTML page will load Dojo 1.5 from Google's CDN:

<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"></script>

Alternatively, you can download Dojo to your own server and load it from there. My preferred method is to load from a CDN, but to have a local fallback should something go wrong on the CDN server. To do this, download Dojo and place the files in a suitable place relative to

Page 2: Dojo From the Ground Up

where you will store your web content. Assuming the relative path from your web content to the Dojo script files is "script/", the code in Listing 1 will try to load Dojo from the CDN first, and if it fails it will load the local version instead.

Listing 1. Loading Dojo from CDN with local fallback

<script src="https://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"></script><script>typeof(dojo) === "undefined" && document.write(unescape('%3Cscriptsrc="js/libs/dojo-1.5.min.js"%3E%3C/script%3E'))</script>

It's important that the code starting with typeof(dojo) is all placed on a single line; otherwise, it won't work. If you want to test that the fallback is working, simply comment out the line that loads from the CDN and test your page with the "Hello, World!" example you'll create in a few moments.

Using the Firebug console

Rather than needing to create a web page to try out Dojo, many of the examples in this article are performed using an excellent Firefox plug-in, Firebug. Firebug provides JavaScript developers with full console logging, debugging, and network monitoring facilities, which make the process of testing and fixing issues in JavaScript applications much easier. Some other web browsers actually include these features, but in this example I use Firefox and Firebug as they are available on a wide variety of platforms.

First, you must install Firefox and Firebug (see Resources for download information). After Firefox is installed, launch it and then download and install the Firebug plug-in. With Firebug installed, you should see a bug icon like the one shown in Figure 1 in the lower right corner of your Firefox window. Clicking this icon should open the Firebug window.

Figure 1. Firebug icon and window

To use the Firebug console, click the Console tab. You may need to enable the console first by clicking the down arrow in the tab and clicking Enable. Now, in the console window, enter the following code: console.log("Test");.

You should see a result like the one shown in Figure 2, with a message that the JavaScript debugger is being enabled to support the console.

Page 3: Dojo From the Ground Up

Figure 2. Using the Firebug console

Hello, World!

Next up, let's test out Dojo. For the "Hello, World!" example, you'll use Dojo to attach a function when the DOM has finished loading (see Listing 2). This function simply prints a message "Hello, World!" to the end of the page. Okay, so this won't exactly change the way you create web applications, but what it will do is allow you to ensure that Dojo is available on your page. You will also load this page throughout this article to explore Dojo features using the Firebug console.

Listing 2. listing1.html: Dojo Hello World application

<html><head> <title>Exploring Dojo</title></head><body><h1>Exploring Dojo</h1><div id="message">This is a DIV element with id attribute message.</div><ul id="list"> <li>This is the first item in a list</li> <li class="highlight">This is the second item in a list</li> <li>This is the third item in a list</li></ul><script src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"></script><script>dojo.addOnLoad(function() { dojo.create( "div", { "innerHTML": "Hello, World!" }, dojo.body() );});</script></body></html>

This script will attach an anonymous function that fires when the DOM has finished loading. This function uses dojo.create to build a new DOM <div> element, setting its innerHTML property to "Hello, World!", and inserting it into the page body using the utility function dojo.body. The result of this is shown in Figure 3. You'll notice that the "Hello, World!" message has been appended to the end of the page body.

Page 4: Dojo From the Ground Up

Figure 3. The "Hello World" page in all its glory

Don't delete this page or close it for now. In the next section, you will be using this page for the sole purpose of loading Dojo, and you will try out some aspects of Dojo directly using the Firebug console.

Before moving on to the next section, it's important to point out something about the positioning of the JavaScript on the page. You may notice that rather than including Dojo and the page JavaScript in the <head> section of the HTML document, I have added it to the end of the page, just before the closing <body> element. The reason for this is that when JavaScript is placed there, it will not block other elements of the page from loading. When using JavaScript libraries in your page, it's important to ensure that they don't block other parts of your page from loading so the performance of your page is optimized. For further information on this, see Resources.

The basics

In this section, you will learn some of the useful functions Dojo provides that make it easier to work with the DOM and arrays. To try out the examples in this section, keep the page you created in the last section open in Firefox and type the code presented in the Firebug console window.

DOM utility functions

The DOM utility functions make it easier to work with the elements in the DOM by providing the ability to find items by their ID or using CSS3 selectors. There are also functions for creating and destroying elements as well as for manipulating the contents of existing elements.

dojo.byId

The dojo.byId function lets you select a DOM node by its id attribute. This function is an alias to the standard JavaScript document.getElementById function, but is obviously shorter to write and also takes care of some cross-browser inconsistencies. Let's use the Firebug console now to log the contents of the DOM element with the ID "message": dojo.byId("message").innerHTML;.

In the left side of the console you should see the response shown in Listing 3.

Listing 3. Response

>>> dojo.byId("message").innerHTML;"This is a DIV element with id attribute message1."

The first line in Listing 3 simply echoes the command that was issued. The second line is the result of that command, in this case, the contents of the <h1> element with ID "message".

Before moving on, let's do something a bit more interesting. In the console editor area, enter the command shown in Listing 4.

Page 5: Dojo From the Ground Up

Listing 4. dojo.fadeOut command

dojo.fadeOut({ node: dojo.byId("message"), duration: 600}).play();

You should see the element fade out and disappear from the page. To fade it back in, change the fadeOut reference in the command to fadeIn and run it again. Pretty neat, huh? This demonstrates how you can dynamically manipulate the current page using the Firebug console. Of course, these changes only apply to the current page load and won't be persisted if you navigate away from the page or refresh it.

dojo.query

In the last section, you learned how to get a reference to a single DOM element using its id attribute. As useful as this is, it isn't feasible to add this attribute to every element you want to interact with. Also, an id must be unique. So what if you want to reference several elements at once? This is where the dojo.query function steps in.

Say you want to get a reference to all of the <li> children of the unordered list with the ID "list" in your page and print out the contents of each of these elements to the console. Thanks to dojo.query, this is really simple (see Listing 5).

Listing 5. dojo.query command

dojo.query("#list li").forEach(function(item) { console.log(item.innerHTML);});

This should produce the output shown in Listing 6 in the console.

Listing 6. Output in the console

>>> dojo.query("#list li").forEach(function(item) { console.log (item.innerHTML); });This is the first item in a listThis is the second item in a listThis is the third item in a list[li, li.highlight, li]

The dojo.query function accepts a string argument with a CSS3 selector reference to the elements that you want to select. In this particular instance, you are saying that you want to select all li elements that are children of the element with the ID "list". The function returns an array of elements that match the query. In the example in Listing 6, you use the dojo.forEach function to iterate over this array and log the innerHTML property of each element found to the console. You will learn more about this function and other array functions in the next section.

Before moving on, let's use dojo.query to find any HTML elements with the class name highlight and apply some styling to make them stand out (see Listing 7).

Listing 7. Using dojo.query to find any HTML elements with the class name highlight

dojo.query(".highlight").style({ backgroundColor: "yellow", color: "red"});

You should notice that the second item in the unordered list on the page changes to have a yellow background, with the text color changing to red. You may notice that in this case the dojo.forEach function was not used. I will cover why this was not needed in the next section, "Arrays and NodeLists."

Other useful utility functions

In addition to the DOM querying and element selection, there are a number of other utility functions available in Dojo that make working with the DOM much easier. You have already seen a couple of these in the "Hello, World" example. The dojo.body function simply returns a reference to the <body> element of the document, dojo.body, and returns the document object itself. dojo.create lets you quickly create a new element, define its attributes, and place it in the DOM.

Page 6: Dojo From the Ground Up

Other functions that exist include dojo.place, which lets you place existing or new elements anywhere in the document. dojo.empty does just what you'd expect it to—it empties the content of a DOM element. dojo.destroy removes a node, taking any child elements along with it. For more information on any of these functions, see Resources to get a link to the Dojo reference documentation.

Arrays and NodeLists

Arrays let you store a collection of values and are available in standard JavaScript. In Dojo, arrays are extended to include several helper functions. These extended arrays are referred to as NodeLists. A NodeList can make use of any standard array functions as well as the additional Dojo-specific functions. When you use the dojo.query function described in the previous section, the return value is a NodeList (or dojo.NodeList to be specific) object. Let's look at some of the functions available in NodeLists.

dojo.forEach

The first function worth discussing is the dojo.forEach function, which you have already seen in the dojo.query example from the previous section of this article. This function lets you define an iterator on a NodeList, supplying a function that will be applied to each item in the NodeList. Let's look at a more basic example in Listing 8.

Listing 8. Basic example

var list = ['My','name','is','Joe'];dojo.forEach(list, function(item, i) { console.log((i+1)+'. '+item);});

This code in Listing 8 produces the output shown in Listing 9.

Listing 9. Output

>>> var list = ['My','name','is','Joe']; dojo.forEac...item, i) { console.log((i+1)+'. '+item); });1. My2. name3. is4. Joe

As you can see, the forEach function takes each item in the array and performs the attached function on it. Above, you used an anonymous function, but you could also use a named function, as shown in Listing 10.

Listing 10. Iterating over an array with dojo.forEach using a named function

var list = ['My','name','is','Joe'];

var printArray = function(item, i) { console.log((i+1)+'. '+item);}

dojo.forEach(list, printArray);

dojo.indexOf

The dojo.indexOf function lets you find what position in an array a particular value is at. The best way to illustrate it is by way of example. Using the list array created in the previous section, try to work out the index of the array the value name is at: dojo.indexOf(list, "name");.

This returns the result shown in Listing 11.

Listing 11. Result

>>> dojo.indexOf(list, "name");1

So the name value is at index 1 in the array. Remember that JavaScript arrays start at index 0, so this value is the second item in the array. If you try to use this function supplying a value that isn't in the array at all, the return value is -1.

Page 7: Dojo From the Ground Up

This function returns the first index found for the given value, so if there are multiple items in the array with the same value, it will stop at the first item. Dojo provides a similar function, dojo.lastIndexOf, which lets you find the last index of a particular value. This function works the exact same way as dojo.indexOf.

dojo.filter

The dojo.filter function enables you to create a new array that is a filtered version of another array. For example, if you wanted to create a new version of the list array you created earlier, but exclude any items with the value is, you could use the code shown in Listing 12.

Listing 12. Filtering an array to create a new array

var filteredList = dojo.filter(list, function(item) { return item != "is";});

dojo.forEach(filteredList, "console.log(item)");

This results in the following output:

>>> var filteredList = dojo.filter(list, function(it...dojo.forEach(filteredList, "console.log(item)");MynameJoe

Other NodeList functions

Dojo contains some other NodeList functions that are useful when working with arrays. The dojo.map function lets you create a new array that is a modified version of an existing array. For example, you might have an array of numbers that represent monetary values. You could use a map function to return an array of these values in a currency format. dojo.some lets you check if at least one item in an array matches specified criteria. Similarly, dojo.every is used to check if every item in an array matches specified criteria. For a full list of NodeList functions and their associated documentation, see Resources.

Event handling in Dojo

Most JavaScript libraries have a cross-browser implementation of native JavaScript event handling, allowing you to attach functions to be called when a DOM event is triggered. As useful as this may be, Dojo takes the concept a step further by letting you connect functions to other functions, which can be DOM events, object events, user-defined functions, or "topics," which are discussed later in this section.

DOM event handling

The first way of attaching functions to DOM events is to use the dojo.connect function. The best way to illustrate this is by way of example. In the Firebug console, enter the code in Listing 13.

Listing 13. Attaching functions to DOM events using dojo.connect

var message = dojo.byId("message");dojo.connect(message, "onclick", function() { alert(message.innerHTML);});

This results in the output shown in Listing 14 in the console.

Listing 14. Output

>>> var message = dojo.byId("message"); dojo.connect..., function() { alert(message.innerHTML); });[div#message, "onclick", function(), 1]

That's great and all, but isn't the function supposed to actually do something? Absolutely. Dojo has attached a function to the click event handler of the element with the ID "message". To try it out, click on the message on the screen with the content "This is a DIV element with id attribute message." You should see a JavaScript alert box, as shown in Figure 4.

Page 8: Dojo From the Ground Up

Figure 4. Attaching functions to DOM events

Nice and easy, isn't it? What if you want to attach an event to all the items in an array? For example, let's say you wanted each item in the unordered list on your page to highlight in bold when you click on them. You could easily do this with the code in Listing 15.

Listing 15. Attaching events to an array of elements

dojo.query("#list li").forEach(function(item) { dojo.connect(item, "onclick", function() { dojo.style(item, { fontWeight: "bold" }); });});

Try it out, it works. Dojo lets you write this piece of code in an even more concise way. Instead of using forEach to iterate over the array, you can use a NodeList.connect shortcut function to do it instead, as shown in Listing 16.

Listing 16. Attaching events to an array of elements (improved)

dojo.query("#list li").onclick(function(e) { dojo.style(e.target, { fontWeight: "bold" });});

Because you have already attached an event to the list, you should refresh the page before trying the code in Listing 16 to make sure it works. The e argument is a reference to the Event object, and the target property of this object lets you identify the element that fired the event. You use this to identify the element that the bold styling should be applied to. Try clicking on the three list items; each of them should become bold after you click them.

Connecting functions to other functions

In the previous examples, you connected functions to DOM events. Dojo also lets you connect functions to other functions in the same manner. An example of this might be a function that shows a spinning wheel image somewhere on your page. When a user performs an Ajax function, you want to show this image. Similarly, when the function has returned a response, you want to hide the image. Without using dojo.connect, your code might look like Listing 17.

Listing 17. Connecting functions to other fucntions without dojo.connect

function toggleImage() { //Code to show/hide loading image goes here}

function callAjax() { toggleImage(); //Code to call Ajax function goes here}

function handleResponse() { //Code to handle Ajax response goes here toggleImage();}

While there's nothing wrong with this code, the toggleImage function call is fixed in both the callAjax and handleResponse functions. If you wanted to add another function call, you would have to modify these functions again to include the extra call. Instead of adding the function call to the functions themselves, you can use dojo.connect to establish the link between them. Listing 18 shows how the dojo.connect method might look.

Page 9: Dojo From the Ground Up

Listing 18. Connecting functions to other functions with dojo.connect

function toggleImage() { //Code to show/hide loading image goes here}

function callAjax() { //Code to call Ajax function goes here}

function handleResponse() { //Code to handle Ajax response goes here}

dojo.connect(callAjax, toggleImage);dojo.connect(handleResponse, toggleImage);

This style of coding might not be to every developer's taste, but it allows you to organize your code in a manner that makes it much easier to read.

Publishing and subscribing to topics

The final aspect of Dojo event handling worth mentioning is the ability to publish and subscribe to topics. This lets Dojo components interact with each other, even if they are not aware of each other's existence. For example, let's say that you were defining a topic named printName, which expects a message object with a person's first name and last name. You might have a component that subscribes to this topic, which will print the name to the console any time another component publishes to this topic with a person's name. Listing 19 shows an example of such a subscription (feel free to try it in Firebug).

Listing 19. Subscription

dojo.subscribe("printName", function(msg) { console.log("The person's name is: "+msg.first_name+" "+msg.last_name);});

To publish to this topic, you need to pass an array of objects that adhere to the topic's API (in this case, the objects must have a first name and last name). Listing 20 is an example.

Listing 20. Publishing to a topic

dojo.publish("printName", [ { first_name: "Joe", last_name: "Lennon" }]);

This produces the output shown in Listing 21.

Listing 21. Output

>>> dojo.publish("printName", [ { first_name: "Joe", last_name: "Lennon" } ]);The person's name is: Joe Lennon

As you can see, by publishing this object to the printName topic, your subscribed function has output a corresponding message to the console.

Empowering Ajax with dojo.xhr*

Creating Ajax-powered web applications is typically done by creating an XmlHttpRequest (XHR) object, which will make an HTTP request to a given URL, passing a request header and body, and defining callback functions to define what should be done when the response returns with a successful response body or an HTTP failure response. Implementing cross-browser XHRs can be painful to say the least, but, thankfully, Dojo eases that pain significantly with a set of dojo.xhr* functions that let you make GET, POST, PUT, and DELETE requests.

The four functions provided are as follows:

Page 10: Dojo From the Ground Up

xhrGet xhrPost xhrPut xhrDelete

All of these functions follow the same syntax: accepting a single property configuration object as an argument. In this object you can define the various aspects of the Ajax request you want to make. Again, these options are the same across all of the XHR functions.

Configuration options

Some of the more useful configuration options available to the XHR functions are as follows:

urlThis is the URL the HTTP request should be made to. It must live in the same domain and port combination as the page that is making the request.

handleAsLets you define the format that the response should be treated as. The default is text, but json, javascript, xml, and a couple of other options are also available. You will see an example of creating an Ajax request with a callback function that handles a JSON response format later in this section.

formEither a reference to or the string ID representation of a <form> element. The values of each field in the form will be sent along with the request as the request body.

contentAn object containing the parameters you want to pass to the resource in the request body. This object will be mixed in with the values taken from the form property if both are provided.

An example of an XHR function is shown in Listing 22.

Listing 22. Example of an XHR function call

dojo.xhrGet({ url: "save_data.php", content: { id: "100", first_name: "Joe", last_name: "Lennon" }});

This will asynchronously make an HTTP GET request to the save_data.php file in the same location as the document itself. It will pass the properties of the content object to the PHP script as parameters. In PHP, you would then use the $_GET variable to retrieve these values and perhaps save them to a database.

Callback functions

In the previous example, you learned how you might call an Ajax request using dojo.xhrGet. While the example was sufficient for actually making the request, it provided no facility to handle any response. Callback functions are also passed to the configuration object. The following options are available:

loadThis function will be executed when an Ajax request returns a successful response message. The response data and the request object are passed to this function as arguments.

errorThis function will be executed if there is a problem with the Ajax request. This can occur if the URL specified in the Ajax request is invalid, if the request times out, or if some other HTTP error occurs. The error message and the request object are passed as arguments.

handleThis function allows you to combine the load and error callback functions into a single function (useful if you don't really care whether the request results in a success or error).

In the next example, you will create an Ajax call with a load callback function that will load some data from a JSON file and print it to the page.

Working with JSON data

Let's put the dojo.xhr* functions to a better test by creating a more real example. First, create a new file—put this file in the same directory as the listing1.html file—and add some JSON data to it. The contents of the file are shown in Listing 23.

Page 11: Dojo From the Ground Up

Listing 23. data.json — JSON data to be processed by an Ajax request

{ count: 4, people: [ { first_name: "Joe", last_name: "Lennon", age: 25 },{ first_name: "Darragh", last_name: "Duffy", age: 33 },{ first_name: "Jonathan", last_name: "Reardon", age: 30 },{ first_name: "Finian", last_name: "O'Connor", age: 23 } ]}

Now create an Ajax request in Firebug (make sure the listing1.html page is loaded in Firefox so that Dojo is loaded). This request uses the load callback function to process the JSON response and print a table to the page (see Listing 24).

Listing 24. Using Ajax to load and process the JSON data

dojo.xhrGet({ url: "data.json", handleAs: "json", load: function(data) { var table = "<table border=\"1\">"; table += "<tr><th>Name</th><th>Age</th></tr>"; dojo.forEach(data.people, function(person) { table += "<tr><td>"; table += person.first_name+" "+person.last_name; table += "</td><td>"; table += person.age; table += "</td></tr>"; }); table += "</table>"; dojo.place(table, dojo.body()); }});

Try the code shown in Listing 24 in Firebug. A table should be dynamically added to your page with the data loaded from the JSON file. This is shown in Figure 5.

Page 12: Dojo From the Ground Up

Figure 5. Ajax-loaded table from JSON data

In a real-world example you would use a server-side language like PHP, Python, ASP.NET, or Java to generate the JSON data dynamically based on the parameters passed to it by the Ajax request.

Conclusion

In this part of the Dojo from the ground up article series, you learned about Dojo and the basics of how to use it. In particular, you learned about the various DOM utility functions, array functions, event handling, and XHR features. In the next part of the series, you will learn how to use Dojo's Java™-like class-based object orientation features.

Page 13: Dojo From the Ground Up

Dojo from the ground up, Part 2: Mastering object-oriented development with Dojo

Joe Lennon, Product Manager, Core International

Summary:  The Dojo toolkit enables web application developers to create Rich Internet Applications by offering a wide variety of features that save development time and effort. From DOM helpers and Asynchronous JavaScript and XML (Ajax) to a full-blown widget library and object-orientation features, Dojo includes virtually everything you need to build large-scale Ajax-powered web applications. If the functions you are looking for are not included in Dojo itself, it's likely that you can find them in DojoX, a repository of extensions and experimental features that are not included in the Base or Core modules of the toolkit. In Part 2 of this three-part series on developing rich web-based applications using the Dojo toolkit, you will learn about JavaScript's object-orientation features, and how they differ from a traditional class-based object-oriented programming language. You will then see how Dojo bridges this gap by offering a class-based system of its own.

What is object-oriented development?

Object-oriented programming (OOP) is a software development paradigm that is based on the definition of data structures called objects, which consist of data properties and functions. These properties (member variables) and functions (or methods) define the potential interaction that a piece of software can perform with that object. The primary benefit of OOP is that it helps with code re-use and maintenance by making it easier to organize your code.

Basics of object-orientation

The basic premise of object-orientated programming is that you create objects in your software that define a series of properties that apply to that object and a series of methods or functions that can retrieve or modify the object's properties. A simple example of an object might be a car. The data properties associated with a car might include its manufacturer, model number, registration number, color, cubic capacity, and so on. The methods you might find a car object providing include accelerate, brake, change gear, turn, stop, and so on. In OOP, the idea is that you define the basic properties and methods that are common to all cars, then each individual car will take the form of that definition, albeit with different values to one another. As you will see later in this article, there are different types of approaches to object-orientation in software development.

Common OOP terminology

To get the most out of this article, you should be at least familiar with object-oriented programming and its concepts. Following are basic descriptions of some common terminology used when discussing object-oriented development. It is worth pointing out that not all types of OOP incorporate each of these aspects; for example, there are no classes in prototype-based object languages such as JavaScript.

Class

In class-based object-oriented development, a class defines the different properties and functions that make up an object. The class defines the template from which objects are generated, so they should define the common attributes and actions that these objects can adhere to. A class is typically made up of member variables and methods.

Member variables

A member variable of an object is an attribute or property of the object. In the car example I offered earlier, these attributes may include things like the car's manufacturer, model, color, cubic capacity, and so on.

Methods

A method is an action that an object can perform. For example, a car can accelerate, brake, turn, and so on. Often, a method will modify the value of a member variable. For example, when a car object accelerates using the accelerate method its current speed property will increase. Many objects will have a special method called a constructor, which is always called instantly whenever an object is created.

Instance or object

An instance or object is the actual object itself, rather than a template for defining an object. For example, you might have an object called myCar, which has the properties and methods of a car template. In the instance of an object, the properties would actually have values. So, for example, myCar might have a color property with a value of silver and a cubic capacity property of 2500. The current values of an object's properties are referred to as its state, and its state can change throughout the life cycle of the object.

Inheritance

In class-based OOP, inheritance is the process in which a subclass or child class inherits the member variables and methods of its superclass or parent class. In addition to inheriting these attributes and actions, a subclass can define member variables and methods of its own and

Page 14: Dojo From the Ground Up

provide default values for properties of the parent class. For example, you might have a FourByFour class, which is a subclass of the Car class. This subclass may set the drivetrain attribute of its superclass to default to 4WD (four wheel drive). In addition, it may define another attribute with the name transfer case that only applies to 4x4 vehicles as well as a method that lets you change the low range gear that is not available on regular vehicles.

Encapsulation

In class-based OOP, member variables are often declared as private so they cannot be accessed or modified outside the confines of the class itself. There are special methods known as modifiers that let you define methods that will either retrieve or modify the value of private member functions in the class. These methods (often referred to as getters and setters) allow a programmer to use information hiding to only make certain properties accessible to applications and other classes. This technique is often referred to as encapsulation.

Abstraction

Abstraction is the process of reducing the complexity of your objects by only defining those properties and methods that are significant to an object in its current context. For example, when defining a Car class, you could abstract the class further to a Vehicle class by defining all the properties that a car has that are also common to other types of vehicles such as vans, trucks, motorcycles, and so forth. The Car class would then inherit these properties from the Vehicle class, as would a Motorcycle class or Van class.

Polymorphism

In the context of OOP, polymorphism means that a subclass can inherit methods from its superclass without having to provide the same implementation for everything. Take an example where you may have two subclasses of the Car class, one for cars with automatic transmission (let's call it ATCar) and another for cars with manual transmission (say, MTCar). All Car objects can accelerate, so both ATCar and MTCar would inherit the accelerate method from the parent class. However, in an ATCar your accelerate method would automatically call the change gear method when the engine reaches a certain level of RPM. As a result, you override the parent class' definition of the accelerate method in the ATCar subclass, while in MTCar the method would remain the same as the one that it inherits from the Car class.

This article is not meant as an all-encompassing guide to object-oriented programming. If you are uncomfortable with the concepts outlined above, it would be well worth your while jumping to Resources and reading more about OOP before continuing this article.

Object-oriented JavaScript

Many of the concepts presented in the previous section are exclusive to a specific OOP paradigm referred to as class-based object-oriented programming. However, not all programming languages adhere to this paradigm. Another common type of OOP is prototype-based object-orientation, and this is the paradigm used in the JavaScript language. In this section, you learn a little more about JavaScript's implementation of object orientation, an example of how to use it, and some stumbling blocks that you may find, particularly if you come from a class-based OOP background.

JavaScript is not just a basic scripting language

When JavaScript first gained popularity, it was primarily used as a means of performing simple tricks on basic web pages. The majority of the people who used JavaScript were not software developers, they were graphic or web designers who may have had a lot of experience with HTML, but had little or no knowledge of programming languages. HTML on its own is quite limited in terms of allowing someone to produce dynamic effects, and this is where JavaScript came into play. However, rather than actually learning how to program in JavaScript, the majority of designers would just find the snippet of code they needed, learn enough to know how to tweak it to their own specific needs, and then use that small piece of code. When the designer goes through this process several times, they can feel that they have an acceptable level of knowledge of JavaScript.

In the early days of the web, JavaScript was quite limited. However, it has grown into a mature and full-featured programming language, which is no longer just used to write simple tricks for websites, but to power entire rich Internet applications. In fact, JavaScript as a language is also used today in various other ways. The CouchDB document-oriented database management system, for example, uses JavaScript functions to query data in the database.

Many Java developers (and developers in other more traditional programming languages) may look down on JavaScript and see it as a basic scripting language. Although JavaScript has evolved to become very powerful, the mentality that it is just used to do tricks on websites remains. This is because most web developers who use JavaScript will use libraries and frameworks such as jQuery, Prototype, or Dojo to take the pain out of writing JavaScript for them. In fact, many web developers could be considered experts in writing jQuery applications, but actually have little expertise in JavaScript itself. The thing that many of these developers are missing is that vanilla JavaScript is actually very powerful and includes object-orientation features out of the box. In this section, you learn about these features.

Prototype-based OOP

JavaScript implements a type of object-oriented programming different to that used in Java™ code. Whereas Java programming is based on a class-based OOP model, JavaScript is based on a class-less-based OOP model commonly known as prototype-based object-orientation.

Page 15: Dojo From the Ground Up

Rather than defining a set of class templates from which objects are created, objects are simply declared when needed. When an object needs to inherit features from another object, it can simply clone the features of a prototype object. One of the key advantages of prototypal OOP is that an object prototype can be modified at run time, meaning that the definition of the structure of objects is not strict. Most class-based OOP programming languages do not allow the class to be dynamically altered at run time (although there are a few exceptions such as Perl, Python, and Ruby).

In the next section, you learn how to work with OOP in vanilla JavaScript using the prototype model.

Example of basic object orientation in vanilla JavaScript

In Part 1 of this article series, you learned about the Firebug plug-in for Firefox and how you can use the console to run JavaScript code without having to edit, save, and run files and perform events on a web page. Open Firefox and launch Firebug. It doesn't matter what web page you are currently on, as this example does not require any particular JavaScript libraries.

Rather than declaring classes in JavaScript, you create a function that will serve as an object prototype. You can then create an instance of this object using the new keyword. For an example of this, enter the code in Listing 1 into the Firebug console:

Listing 1. A basic object prototype in JavaScript

function Car() { }

var myCar = new Car();console.log(myCar);

This should produce the following output in the console log: Object {}.

You can actually click on this output and it will take you to another part of Firebug that lets you inspect the various properties of an object. If you click on this particular object, you'll see a message "There are no properties to show for this object."

What this code is actually doing is defining an object function Car(). It then instantiates an object using the new operator, and, finally, it outputs the object to the Firebug console where you can inspect it further. This object is hardly going to set the world right, however, so let's make it a bit more interesting (see Listing 2).

Listing 2. Defining a member variable in your object

function Car() { }Car.prototype.current_speed = 0;

var myCar = new Car();console.log(myCar);

This time, the console log will output something a bit more interesting: Object { current_speed=0 }.

Clicking on the output will bring you back to the DOM inspector window, where you can see the property current_speed and a value of 0. Any objects created using the Car prototype function will, by default, have a current_speed property with a default value of zero.

A car is pretty much useless if it can't accelerate, so let's add a method to the prototype (see Listing 3).

Listing 3. Adding a method to the prototype

function Car() { }Car.prototype.current_speed = 0;Car.prototype.accelerate = function(increment) { this.current_speed += increment;}

var myCar = new Car();myCar.accelerate(30);myCar.accelerate(20);

console.log(myCar);

The console output should produce the following: Object { current_speed=50 }.

Clicking the output will show you not only the current_speed property, but also the new accelerate method that is available to the object. In the example in Listing 3, you can see how to call an object's method: you use dot notation like object.method(arg[0], arg[1], ..., arg[N]); in this case, it's myCar.accelerate(20). This same notation can be used to access any particular

Page 16: Dojo From the Ground Up

property of an object. Change the line console.log(myCar) to console.log(myCar.current_speed) and you should see the console output show the value 50 instead of a representation of the actual object itself.

Next, let's investigate how to implement a constructor function in JavaScript. A constructor is a function that is called immediately after an object is instantiated. When you create the object function, this doubles as a constructor function. Listing 4 is an example of this in action.

Listing 4. Adding a constructor function body

function Car(reg_no) { this.reg_no = reg_no; console.log('Car with registration no. '+this.reg_no+' created.');}

Car.prototype.reg_no = '';Car.prototype.current_speed = 0;Car.prototype.accelerate = function(increment) { this.current_speed += increment;}

var myCar = new Car('10C500');myCar.accelerate(30);myCar.accelerate(20);

console.log(myCar.current_speed);

In Listing 4, the Car's constructor function accepts a single argument for its registration number. It then sets the object instance's registration number to the argument value and outputs a message to the Firebug console to confirm that the instance has been created. You should see the output in Listing 5 in the Firebug console output window.

Listing 5. Output

Car with registration no. undefined created.50

To demonstrate how you can implement inheritance on an object prototype, let's create a more advanced Car prototype, complete with methods to accelerate, decelerate, and change gears (see Listing 6).

Listing 6. A more complete Car prototype

function Car(reg_no) { this.reg_no = reg_no;}

Car.prototype.reg_no = '';Car.prototype.current_speed = 0;Car.prototype.current_gear = 0;

Car.prototype.accelerate = function(increment) { this.current_speed += increment;}Car.prototype.decelerate = function(decrement) { this.current_speed -= decrement;}Car.prototype.increaseGear = function() { this.current_gear++;}Car.prototype.decreaseGear = function() { this.current_gear--;}

Now let's create an inherited object prototype from this called ATCar, which describes a car with automatic transmission. This particular example is hardly the perfect car, as it implements gear changes based on speed rather than RPM, but it should help get the idea of inheritance and polymorphism in prototypal OOP across (see Listing 7).

Listing 7. An ATCar object prototype, inheriting from the Car

function ATCar(reg_no) { Car.call(this, reg_no);}

Page 17: Dojo From the Ground Up

ATCar.prototype = new Car();ATCar.prototype.constructor = ATCar;

ATCar.prototype.accelerate = function(increment) { Car.prototype.accelerate.call(this, increment); if(increment >= 10) this.increaseGear();}

ATCar.prototype.decelerate = function(decrement) { Car.prototype.decelerate.call(this, decrement); if(this.current_speed === 0) this.current_gear = 0; else if(decrement >= 10) this.decreaseGear();}

The first thing you'll notice is that the constructor uses the call function on the Car object prototype. This basically will call the constructor on the parent prototype definition whenever an ATCar is instantiated. This lets you ensure that you implement inheritance, where the ATCar prototype does not need to know the inner workings of the Car object prototype. Next, you'll see that you are setting the prototype property of the ATCar function to a new instance of the Car function. This basically tells JavaScript that you want to inherit the properties and methods of the Car prototype in your ATCar prototype.

In Listing 7, you are also overriding the accelerate and decelerate methods so that on automatic cars, acceleration and deceleration will also cause the gears to change automatically. In both of these methods, you are first calling the parent prototype's method so you don't have to re-implement the actual acceleration, saving on repetitive code. This is not so important in this particular example as it is only one line of code, but imagine this was a complex function; repeating it would be painful!

Finally let's see this example in practice (see Listing 8).

Listing 8. Using the automatic car prototype

var myCar = new ATCar('10C500');myCar.accelerate(30);myCar.accelerate(20);myCar.decelerate(5);

console.log(myCar);

This will output the new object you have created. Click on the object to view its detail. The result should look something like Figure 1.

Figure 1. Firebug view of the myCar object properties

This article's primary objective is to show you how to use Dojo's class-based OOP simulation features, and as such, this is only an introduction to vanilla JavaScript's prototypal approach to object-orientation. For further information on prototype based OOP, see Resources.

Problems with prototypal OOP

Different people have different views on whether prototype-based object-oriented programming is better or worse than class-based OOP. Each argument for or against can be fairly easily countered based on your preferences as a programmer. One of the most common problems with prototype-based object orientation, particularly in JavaScript, is the lack of basic understanding that many developers have of it. This is gradually becoming less of an issue, however, as the number of developers who have a deep understanding of JavaScript is steadily

Page 18: Dojo From the Ground Up

increasing. With that said, many programmers who are familiar with class-based OOP languages such as the Java language will still prefer to stick to a class-based system, and Dojo provides some excellent features that simulate this type of system to let you code JavaScript in a similar fashion. The next section explains how to use these features of Dojo to create class-based applications in JavaScript.

Simulating class-based OOP with Dojo

Before discussing Dojo's class-based simulation further, it's important to note that at the end of day, Dojo is still a JavaScript library. Java code and JavaScript are not the same; in fact, they are quite different. Dojo does not try to force JavaScript to act like Java code, but rather it allows you to work with JavaScript OOP in a way that is more familiar to Java (and other class-based OOP languages) developers, with the underlying structure still working in a prototypal fashion.

Creating classes with dojo.declare

To create a class using Dojo, you use the dojo.declare function. Let's create a Car class using this function now (see Listing 9).

Listing 9. Using dojo.declare to create a Car class

dojo.declare("Car", null, {

});

var myCar = new Car();console.log(myCar);

This is the basic shell for creating a class and instantiating an object of that class. The dojo.declare function accepts three arguments:

1. The class name2. The superclass the class should inherit from3. An object comprising any properties and methods for the class

In the example in Listing 9, you declared a class named Car, which does not inherit from any superclass and does not prescribe any member variables or methods. If you look at the object properties for the myCar object by clicking on the output in the Firebug console, you should see something similar to Figure 2.

Figure 2. A basic object created from a Dojo class

As you can see, creating a class in Dojo will give any objects generated from the class some properties and methods by default. Your current class is not very interesting, so let's add some properties and methods and a constructor, like you did when demonstrating the prototype-oriented way of doing so in the previous section (see Listing 10).

Listing 10. A more complete Car class

dojo.declare("Car", null, {

Page 19: Dojo From the Ground Up

reg_no: "", current_speed: 0, current_gear: 0, constructor: function(reg_no) { this.reg_no = reg_no; }, accelerate: function(increment) { this.current_speed += increment; }, decelerate: function(decrement) { this.current_speed -= decrement; }, increaseGear: function() { this.current_gear++; }, decreaseGear: function() { this.current_gear--; }});

As you can see, this style of class declaration is far easier to read and is more together than the vanilla JavaScript way of declaring an object prototype. Before moving on to inheritance, let's check that an object can be instantiated and the methods work (see Listing 11).

Listing 11. Using the Car class

var myCar = new Car("10C500");myCar.accelerate(30);myCar.accelerate(20);myCar.decelerate(5);console.log(myCar.reg_no+" travelling at "+myCar.current_speed+" mph");

This produces the following output in the Firebug console: 10C500 travelling at 45 mph.

Inheritance and multiple inheritance

Next, create your automatic transmission subclass, like you did previously using vanilla JavaScript, but this time using the dojo.declare function (see Listing 12).

Listing 12. Creating the ATCar subclass using Dojo

dojo.declare("ATCar", Car, { accelerate: function(increment) { this.inherited(arguments); if(increment >= 10) this.increaseGear(); }, decelerate: function(decrement) { this.inherited(arguments); if(decrement >= 10) this.decreaseGear(); }});

As you can see from Listing 12, the only thing that is provided in the subclass is any overridden or new properties and methods (in this case, you are just overriding the accelerate and decelerate methods to automatically change gears). Dojo takes care of calling the constructor in the superclass automatically. If you needed to add a constructor function, you can add a constructor function to the subclass, but you don't need to worry about calling the superclass constructor; this is done automatically. You'll notice that in both the overridden methods the line this.inherited(arguments) is called. This will basically call the same method in the superclass. This allows you to avoid rewriting the code to do the actual acceleration, and only facilitate the changing of gears as is provided by the automatic car.

Let's check out the new subclass in action (see Listing 13).

Listing 13. The new subclass in action

var myCar = new ATCar("10C500");myCar.accelerate(30);myCar.accelerate(20);myCar.decelerate(5);console.log(myCar.reg_no+" travelling at "+myCar.current_speed+" mph in gear "+myCar.current_gear);

Page 20: Dojo From the Ground Up

This produces the following output: 10C500 travelling at 45 mph in gear 2.

Dojo also includes support for multiple inheritance. Multiple inheritance allows a subclass to be derived from multiple parent classes, inheriting properties and methods from each of the parent classes. Strictly speaking, only one of these parent classes is considered to be the superclass (the first one in the array), but the constructors of each derived class will be called in the sequence in which they reside in the array of parent classes.

To illustrate multiple inheritance, take the example of a Smartphone, which performs many functions other than just making and receiving phone calls and text messages (see Listing 14). Typically, it will also perform functions such as playing music, watching videos, and much more. Let's keep it simple for the purpose of the example and say that a Phone can make calls, a MediaPlayer can play videos, and a Smartphone can do both.

Listing 14. Multiple inheritance in Dojo

dojo.declare("Phone", null, { phone_number: "", minutes_remaining: 0, constructor: function(properties) { this.phone_number = properties.phone_number; this.minutes_remaining = properties.minutes_remaining; console.log("Phone "+this.phone_number+" powered on. You have "+this.minutes_remaining+" minute(s) remaining."); }});

dojo.declare("MediaPlayer", null, { disk_space: 0, constructor: function(properties) { this.disk_space = properties.disk_space; this.songs = properties.songs; console.log("Media Player powered on. You have "+this.songs.length+" songs,with "+this.disk_space+" GB free space left."); }});

dojo.declare("Smartphone", [Phone, MediaPlayer], { phone_id: "", constructor: function(properties) { this.phone_id = properties.phone_id; console.log("Smartphone ID "+this.phone_id+" boot up complete."); }});

var songs = [ {artist:"U2",title:"Vertigo"}, {artist:"Coldplay",title:"Yellow"}];

var myPhone = new Smartphone({ phone_number:"(555) 123-4567", minutes_remaining: 60, disk_space: 2.5, songs: songs, phone_id: "4345FDFD7JAPO76"});

console.log(myPhone);

The first thing worth pointing out here is how dojo.declare implements multiple inheritance. As you can see, rather than just passing the parent class as the second argument, an array of classes is passed. The constructors of these parent classes will be called automatically in the order they appear in the array. An important thing to note is that if each parent class constructor accepts different arguments, Dojo will not be able to differentiate the arguments that should be passed to each constructor function. As a result, if you do require to pass different arguments to the different constructors, you should add the arguments as key/value pairs in a simple JavaScript and consume them in the constructors that way.

Listing 15 is the output that will appear in the Firebug console.

Page 21: Dojo From the Ground Up

Listing 15. Multiple Inheritance example output

Phone (555) 123-4567 powered on. You have 60 minute(s) remaining.Media Player powered on. You have 2 songs, with 2.5 GB free space left.Smartphone ID 4345FDFD7JAPO76 boot up complete.Object { phone_number="(555) 123-4567", more...}

Clicking on the link in the final line will show the properties of the myPhone object, which should look something like Figure 3.

Figure 3. The myPhone object, inheriting from multiple parent classes

In Figure 3, the different properties for the different classes are all present in the instantiated object of the Smartphone class. The phone_number and mintues_remaining properties of the Phone class are there, the disk_space and songs from the MediaPlayer class are there, and the phone_id member variable from the Smartphone subclass is also there. If any of these classes had methods, these methods would also show up here.

Using dojo.mixin to improve the multiple inheritance example

Dojo provides a nice utility function, dojo.mixin, which lets you mix objects by combining their properties from left to right (see Listing 16).

Listing 16. A basic example of dojo.mixin

var objA = { a: 1, b: 2 };var objB = { b: 3, c: 4 };dojo.mixin(objA, objB);console.log(objA);

After mixing objB into objA, the properties in objA will look like Figure 4.

Page 22: Dojo From the Ground Up

Figure 4. Mixing objects with dojo.mixin

The b property that was initially set to 2 in objA, has been overwritten with the value 3 from objB. Also, the c property has been added. With the basic example finished, let's have a look at how you can use dojo.mixin in your multiple inheritance example.

When creating the Phone class in the previous example, you might recall the two lines in Listing 17 in the constructor for that class.

Listing 17. Lines in the Phone class constructor

this.phone_number = properties.phone_number;this.minutes_remaining = properties.minutes_remaining;

This wasn't too tedious as there were only 2 properties, but what if there were many more? Wouldn't it be a real pain to have to assign the properties in this way? That's where the dojo.mixin function really proves useful. Replace these two lines (and the similar lines in the MediaPlayer and Smartphone classes) with the following line: dojo.mixin(this, properties);.

The result is the exact same as before, but there's no fumbling with the various properties that have been passed to the constructor. Neat, huh?

Packaging and modular development in Dojo

When working with large applications, it is likely that you will have large classes with many member variables and methods. If you come from a Java development background, you will more than likely follow the notion that different classes should reside in different files, grouped by packages. Classes are then "imported" when required for inheritance or other purposes, ensuring they are only loaded when necessary. With JavaScript, there is no such packaging and module system available out of the box, but thankfully, Dojo provides a solution.

For example, in the Car class example, using Java code you might store this in a package, as shown in Listing 18.

Listing 18. Packaging classes in Java programming

package com.ibm.developerworks.dojoseries;public class Car {

//Car class code goes here}

You can later import this class in your other Java classes, as shown in Listing 19.

Listing 19. Importing classes in Java programming

package com.ibm.developerworks.dojoseries;import com.ibm.developerworks.dojoseries.Car;public class ATCar extends Car {

//ATCar class code goes here}

Page 23: Dojo From the Ground Up

Dojo provides a similar packaging system by means of the dojo.provide and dojo.require functions. Let's take a look at how the Java code in Listing 19 might look in Dojo. First, let's look at the Car class in Listing 20.

Listing 20. Packaging classes in Dojo

dojo.provide("com.ibm.developerworks.dojoseries.Car");dojo.declare("com.ibm.developerworks.dojoseries.Car", null, {

//Car class code goes here});

As you may notice, this is quite similar to the Java code, albeit the entire package path for the class is given in the dojo.provide statement, rather than just the path to the containing package. The package path is important, as it also determines where Dojo will look for this class when it attempts to load it using dojo.require. So, for the example in Listing 20, the Car.js file should be stored in a relative path com/ibm/developerworks/dojoseries/Car.js. If it is not stored in this location, Dojo will not be able to load the class correctly when it needs to. Next, let's look at how you can import this class and create a subclass from it (see Listing 21).

Listing 21. Importing classes in Dojo

dojo.provide("com.ibm.developerworks.dojoseries.ATCar");dojo.require("com.ibm.developerworks.dojoseries.Car");dojo.declare("com.ibm.developerworks.dojoseries.ATCar", com.ibm.developerworks.dojoseries.Car, {

//ATCar class code goes here});

You'll notice here that you are using the dojo.provide statement again to identify the path that this class can be loaded from. This particular class would be stored in the relative path com/ibm/develoeprworks/dojoseries/ATCar.js. Next, you use dojo.require to load the Car class using its full package path. Finally, you declare the subclass, passing the full path to the parent class as the second argument. Because this class has now been loaded by Dojo, it is available in the DOM and can be loaded directly by its name, without requiring it to be placed in a string.

Although you can technically have a different class name to the path provided in the dojo.provide statement (note that any loading of classes using dojo.require must use the fully qualified path set out in dojo.provide), it is highly recommended that you do not do this, as it will only lead to confusion.

The next section explains how you can use Dojo's build system to package your application, ensuring it runs at optimal performance and speed.

Packing it all — using Dojo's build system

When working with Dojo's object-orientation features, it is highly likely that you will start separating your classes out into different files to make code organization and management a much easier task. However, it is important to note that loading many small JavaScript files can have serious performance implications for your application. Each time a web browser needs to download and execute a JavaScript file it must make a separate HTTP request, wait for the server to respond, and then process that response. As a result, it is usually much faster to load a single large file than to load many small files.

The problem with using a single large file is that it can be a version control and code organization nightmare, not to mention the fact that it probably contains a large amount of code that isn't actually needed by parts of your application. The solution to this issue is to get the right balance between small file sizes and minimizing the number of HTTP requests your application makes.

This is where Dojo's build system comes into play. It lets you define layers, each of which combine the source code from several JavaScript source files and minify the resulting single file to keep the file size to a minimum. The minification process shrinks your code substantially by removing all unnecessary whitespace and comments, and by renaming local variables to shorter names and re-factoring their usage in functions where applicable. By using the build system, you can keep your source code organized for the purpose of development, but ensure that it works at optimum performance levels when deployed to a production environment.

A guide to using the Dojo build system would probably require an article of its own. Fortunately, the Dojo documentation features extensive coverage of this topic. For more information on how to use the build system, see Resources.

Conclusion

In Part 2 of this three-part series on developing rich web-based applications using the Dojo toolkit, you learned about the basics of object-orientation, how JavaScript uses a prototype-based approach to OOP, and how the long-held perception among many traditional developers about JavaScript not being a powerful OOP-enabled language is wrong. You then learned about JavaScript's vanilla object-oriented features, how to define object prototypes, and how to implement inheritance. You discovered how you could use Firebug to test JavaScript code

Page 24: Dojo From the Ground Up

without having to save code into a file. You then learned how to write JavaScript classes that have a style that is more familiar to Java developers using Dojo's dojo.declare function. You learned how to perform inheritance and multiple inheritance, and how dojo.mixin can make combining properties of objects a breeze. You also learned how Dojo's package and module functions let you separate your classes into individual source files, much like you'd expect in a traditional OO language like the Java language or C++. Finally, you discovered that the Dojo build system lets you develop in a manner that facilitates tidy code organization without impacting on performance by minimizing file sizes and HTTP requests in a production environment.

In the third and final part of this series, you will see how Dojo's widget platform, Dijit, can be used to create interactive and rich Internet applications. Dijit is built on top of Dojo's object-oriented features, so what you have learned in this part of the series should prove useful in the next part.

Page 25: Dojo From the Ground Up

Dojo from the ground up, Part 3: Creating rich user interfaces with the Dijit component framework

Joe Lennon, Product Manager, Core International

Summary:  The Dojo toolkit lets Web application developers create Rich Internet Applications by offering a wide variety of features that save development time and effort. From DOM helpers and Ajax to a full-blown widget library and object-orientation features, Dojo includes virtually everything you need to build large-scale Asynchronous JavaScript and XML (Ajax)-powered Web applications. If the functions you are looking for are not included in Dojo itself, it's highly likely that you can find it in DojoX, a repository of extensions and experimental features that are not included in the Base or Core modules of the toolkit. In Part 3 of this three-part series on developing rich web-based applications using the Dojo toolkit, learn about the Dijit rich user interface component framework, which lets you build powerful interfaces with minimal effort.

What is Dijit?

Dijit is the Dojo Toolkit's user interface library of rich components. These components are fully theme-able, and can be declared either declaratively using HTML-style tags or programmatically using JavaScript. This section provides a brief explanation of Dijit, explains the components it has to offer, and describes the various themes that are available out of the box.

Rich user interface components

The primary feature of Dijit is the suite of rich user interface components it offers. Most web application developers will be all too familiar with the limitations of basic HTML elements and form components as well as the difficulty involved with laying out an application using elements such as <div> and CSS rules. This is where Dijit is really useful. It provides a series of components that are not available in HTML (without writing them yourself, of course) including:

Calendar Color palette Dialog box (modal or non-modal) Rich text editor Inline editor Menu bars and context menus Progress bars Accordions and panels Toolbars Tooltips Trees

In addition to the previous list, the DojoX extension library boasts an array of additional components, including grids, charts, video players, lightboxes, and more. Figure 1 provides examples of many of the Dijit components, including a button, dialog box, tab container, calendar, color palette, menu, rich text editor, and progress bar.

Page 26: Dojo From the Ground Up

Figure 1. Dijit components in action

In addition to UI components, Dijit also provides a series of improved form fields, which offer more flexibility and functionality than the regular HTML form elements. These form controls include:

Various text box controls for specific data formats including currency, date, number, and time Number spinner Auto-expanding text area Auto-completion combo box Multi-selection list boxes Buttons with drop-down menus Toggle buttons (switch on/off) Slider

Figure 2 shows some of these form controls in action.

Page 27: Dojo From the Ground Up

Figure 2. Dijit form controls in action

Dijit also includes various layout components, which make organizing your web application's layout a breeze. No more messing around with tables or CSS floats, Dijit lets you define complex structures for your application layout. The layout components Dijit offers include:

Accordion container Stack container Border container Tab container Content panes

As you have seen, Dijit has a wealth of user interface components that would normally take ages for developers to write themselves. Using Dijit, you can reduce the development time for your applications, as you don't need to worry about designing or developing complex user interface components.

Theming

In the previous section, you saw some examples of Dijit's user interface components, all of which were using the "Claro" theme that comes with Dijit. Dijit also includes several other themes out of the box, allowing you more scope to fit Dijit components to the styling of your application. Figure 3 illustrates some examples of other Dijit themes in action.

Page 28: Dojo From the Ground Up

Figure 3. Tundra, Soria, and Nihilo themes

If the themes included with Dijit are not a good fit for your application, you can easily define your own theme and customize all of Dijit's components to your exact requirements. Creating Dijit themes would justify an entire article of its own, and is covered in great detail in the Dojo toolkit documentation. See Resources for a link to the theming section of the Dojo documentation.

Getting started with Dijit

To create Dijit applications, you need to include the Dojo library itself, the CSS file for the theme you are using, and a reference to your theme selection on the body element of your HTML document. You then load the Dijit components that you are going to include in your application using the dojo.require function.

Let's start off with a basic template for a Dijit application that uses the Claro theme. For the purpose of this article, I am assuming you are loading Dojo from the Google Content Delivery Network (CDN), rather than from your own server or computer. Open your favorite text editor and add the contents of Listing 1 to it.

Listing 1. Basic Dijit template

<!doctype html><html lang="en" dir="ltr"> <head> <title>Dijit Template</title> <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/claro/claro.css" /> <style type="text/css"> body, html { font-family:helvetica,arial,sans-serif; font-size:90%; } </style> </head> <body class="claro"> <!-- HTML content here --> <script src="https://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"djConfig="parseOnLoad: true"></script> <script> dojo.require("dijit.dijit"); //Add Dijit components you are using here using dojo.require

dojo.addOnLoad(function() { //JavaScript content here }); </script> </body></html>

As you can see in Listing 1, the claro.css stylesheet is loaded from the Google CDN. Also, it is important to give your <body> element a class name that matches the name of the theme you are using. In this case, I'm using the Claro theme, so I've given the class name claro. You might think that to include Dijit you need to include a series of JavaScript files in addition to the base Dojo toolkit. This is not the case; you can use Dojo's loading system to dynamically load the elements of the Dijit framework you need using dojo.require. One thing that I have added, however, is the djConfig="parseOnLoad: true" attribute to the <script> tag that loads Dojo. This basically tells Dojo that it should use its HTML parser to look for HTML elements with the attribute dojoType. You will see more about this in the next section. Finally, inside the main application script, I have added a dojo.require declaration for "dijit.dijit", which optimizes the loading of Dijit. With the template defined, you are now ready to use Dijit components in your application.

There are two ways of working with Dijit components in your application. The first way is to add your components declaratively. This means adding to your page HTML elements that use the dojoType attribute to indicate a component should be parsed by Dojo and rendered as a Dijit component. You will see how this works in the next section. The other way of adding components is to use JavaScript to define your components programmatically. You will see more about this shortly.

Page 29: Dojo From the Ground Up

Working with Dijit declaratively

A very useful feature Dijit provides that is not available in most other major JavaScript component libraries is a method of using widgets in a declarative way—in other words, using regular HTML elements. The obvious advantage of this is that it lets you design your application using HTML syntax, as you would expect in a web application, keeping your application logic separate in JavaScript.

Using Dijit this way is very straightforward. Let's take a look at an example of creating a calendar component. First, in the <body> section of your template, find the comment <!-- HTML content here -->, and replace it with the following line: <div dojoType="dijit._Calendar"></div>.

Next, below the line dojo.require("dijit.dijit");, add the following line: dojo.require("dijit._Calendar");.

Save this file and load it in your favorite web browser. You should see something similar to the screenshot in Figure 4. Pretty neat, huh?

Figure 4. Dijit calendar component in action

Declaring Dijit components in this way is by far the easiest way to add Dojo to your applications. You can add widgets inside other widgets where applicable (for example you could add a color palette inside a TitlePane), and you can even attach event handlers to your components in a fairly simple way.

First, let's nest a widget inside another widget, as described in the previous paragraph. Replace the calendar line in the HTML section with the snippet in Listing 2.

Listing 2. Snippet for adding a color palette inside a title pane

<div dojoType="dijit.TitlePane" title="Color Picker"> <div dojoType="dijit.ColorPalette"></div></div>

Next, replace the calendar's dojo.require call with the code in Listing 3.

Listing 3. Replacing the calendar's dojo.require call

dojo.require("dijit.TitlePane");dojo.require("dijit.ColorPalette");

Save the file and reload your web browser. You should see something like Figure 5.

Page 30: Dojo From the Ground Up

Figure 5. Color palette inside a title pane

As you can see, the color palette appears inside the title pane component, and if you collapse the title pane, the color palette will not appear. Now, let's add an event handler to the color palette in two ways. First, use an inline onClick attribute that shows an alert window with the selected value when a user selects a color. To do this, change the HTML element for your dojo.ColorPalette object to the following: <div dojoType="dijit.ColorPalette" onChange="alert(this.value);"></div>.

Save the file and load it in your browser, and try clicking on a color. You should see an alert window with the hex value of the color you selected shown. Inline event handlers are fine for one-line actions, but if you wanted to do something a bit more complex, it would not be so useful. Thankfully, you can declare dojo/method <script> blocks to add JavaScript code to your Dijit components.

Replace the line you changed a moment ago with the code in Listing 4.

Listing 4. Dojo Method <script> blocks in action

<div dojoType="dijit.ColorPalette"> <script type="dojo/method" event="onChange" args="evt"> alert(this.value); </script></div>

Save the file and reload your browser, and you'll see that it does the same thing. This time, however, you have added a <script> block inside the Dijit component HTML element. Rather than the traditional text/javascript type value, you've given it a value of dojo/method, which tells the Dojo parser to parse this block of code. It uses the event attribute to define what event it should bind this code to, and uses the args attribute to pass any arguments to the function.

The declarative syntax is one of my personal favorite features of Dojo, as it makes it extremely simple to mock-up fairly complex application designs. It also provides a means of developing complex web applications for those who are not so comfortable with JavaScript. In the next section, you'll see how you can do all of this using JavaScript.

Working with Dijit using JavaScript

Although not as basic as using Dijit in a declarative manner, adding components programmatically is also pretty simple. Let's start off by creating the basic calendar example, like the one created in the previous section. Starting from your basic Dijit template (Listing 1), add the following line to your main HTML section (replacing the comment <!-- HTML content here -->): <div id="myCalendar"></div>.

Now, after the line dojo.require("dijit.dijit");, add the following: dojo.require("dijit.Calendar");.

Page 31: Dojo From the Ground Up

Finally, inside the dojo.addOnLoad function block, add the following line: var calendar = new dijit.Calendar({}, "myCalendar");.

Save the file and load it in your browser. You should see the same calendar that you saw in Figure 4. In this instance, you have added a basic placeholder element to your HTML code with the ID myCalendar. Then, you created your calendar programmatically using the expression new dijit.Calendar. The first argument to this function is a configuration object (which is empty in this example). The second argument is the ID of the HTML element the component should bind to, in this case myCalendar. Easy as cake, right?

What about nested components? Let's go ahead and write the example where you had a color palette inside a title pane. First, the HTML section should contain: <div id="myTitlePane"></div>.

Next, you need the following dojo.require statements in Listing 5 (in addition to dijit.dijit, of course).

Listing 5. dojo.require statements

dojo.require("dijit.TitlePane");dojo.require("dijit.ColorPalette");

And, finally, the code in Listing 6 should be placed inside the dojo.addOnLoad block.

Listing 6. Creating a title pane and color palette programmatically

var colorPalette = new dijit.ColorPalette({});var titlePane = new dijit.TitlePane({ content: colorPalette, title: "Color Picker"}, "myTitlePane");

Save and load the file in your browser, and you'll get a result as shown in Figure 5. Before looking at event handling in programmatic Dijit components, let's see an alternative way of writing the above code. Replace the HTML block with the code in Listing 7.

Listing 7. Using nested HTML elements to lay out components

<div id="myTitlePane"> <div id="myColorPalette"></div></div>

And the dojo.addOnLoad block should contain the code in Listing 8.

Listing 8. Binding nested components using just IDs

var colorPalette = new dijit.ColorPalette({}, "myColorPalette");var titlePane = new dijit.TitlePane({ title: "Color Picker"}, "myTitlePane");

In this version, you have added the color palette inside the title pane using the HTML elements they are bound to. In JavaScript, you then bind both components using IDs, meaning you don't have to add the color palette to the title pane using the content attribute. I prefer this method, as the HTML structure gives the page more semantic meaning and makes it easier to see the layout of the page from the HTML syntax.

Finally, let's see how to add event handling to Dijit components that are declared programmatically. Replace the line var colorPalette = new dijit.ColorPalette({}, "myColorPalette"); with the code in Listing 9.

Listing 9. Adding event handlers to programmatically created components

var colorPalette = new dijit.ColorPalette({ onChange: function(evt) { alert(this.value); }}, "myColorPalette");

Save the file, reload your browser, click on one of the colors, and presto, you should see the hexadecimal value of the color you selected. Alternatively, you could have left the line as it was and added the code in Listing 10 below it.

Page 32: Dojo From the Ground Up

Listing 10. Adding event handlers using dojo.connect

dojo.connect(colorPalette, "onChange", null, function(evt) { alert(this.value);});

It's important to point out that the name of the event is case sensitive in Dijit components. Dojo uses all lowercase for events on regular DOM objects, and camel case for events on Dijit components (camel case is where the first word is lowercase and any following words have the first letter capitalized), so be sure to use the latter when working with Dijit components.

Using dijit.byId

If you read the first article in this series, you will be familiar with the dojo.byId function, which gets a reference to a DOM element. Similarly, Dojo provides a dijit.byId function that lets you get a handle on a Dijit component. This is particularly useful when you are creating components declaratively and want to interact with them in your JavaScript code. Let's look at an example.

From the basic Dijit template (Listing 1), add the following code to the HTML section: <button id="myButton" dojoType="dijit.form.Button">Push Me</button>.

Next, in your dojo.require section, add the lines in Listing 11.

Listing 11. Use dojo-require

dojo.require("dijit.form.Button");dojo.require("dijit.Dialog");

Finally, let's get a reference to the button using dijit.byId, and display a dialog box when the button is clicked. Add the code from Listing 12 inside the dojo.addOnLoad function block.

Listing 12. Connecting to a button using dijit.byId

var button = dijit.byId("myButton");dojo.connect(button, "onClick", null, function(evt) { var dialog = new dijit.Dialog({ content: "You clicked the button!", title: "Message" }).show();});

Save the file and open it in your browser. Click the button and you should see a pretty dialog box, as shown in Figure 6.

Figure 6. Button and dialog box

Page 33: Dojo From the Ground Up

Using Dijit's layout features

In addition to some very useful components and form controls, Dijit also provides an excellent layout framework, which makes it much easier to organize the interface of your application. This section explains how to use Dijit's various layout components. For the sake of brevity, all examples are provided using Dojo's declarative syntax, but it should be relatively straightforward to convert them to the programmatic method should you want to do so.

Content panes

Content panes are the most basic of Dijit's layout components. They allow you to define a section of content that is loaded either by supplying the HTML code directly to the content attribute, or is loaded asynchronously with an XmlHttpRequest call. In the case of the latter, the content pane will display a loading message while the content is being loaded from the server.

Let's take a look at a very basic example of a content pane in action. First, create a new file and name it something like content.html, and add the following code to it: <h1>content.html content here!</h1>.

Now, from your basic Dijit template (see Listing 1), add the code from Listing 13 to the HTML section of the template.

Listing 13. Using Dijit content panes

<button dojoType="dijit.form.Button" id="myButton"> Load content using XHR</button><div dojoType="dijit.layout.ContentPane" id="myContentPane"> <h1>Static content here!</h1></div>

Next, add the code in Listing 14 to the dojo.require section

Listing 14. Adding a content pane to the dojo.require section

dojo.require("dijit.form.Button");dojo.require("dijit.layout.ContentPane");

Finally, connect the button and the content pane to load content.html into the content pane. Add the code in Listing 15 inside dojo.addOnLoad.

Listing 15. Connecting the button to the content pane

var button = dijit.byId("myButton");var contentPane = dijit.byId("myContentPane");

dojo.connect(button, "onClick", null, function(evt) { contentPane.attr("href","content.html");});

Save the file and load it in your web browser. You should see a message like Figure 7.

Figure 7. Before loading via XHR

Page 34: Dojo From the Ground Up

Now, click the button and the message should change.

Figure 8. After loading via XHR

Admittedly, this example is very simplistic, but it should illustrate just how easy it is to load dynamic content into a Dijit ContentPane component. This component is actually used in other Dijit components like Dialog, to render the content section. They are also more frequently used in layout containers like stack containers and tab containers, as you will see in a moment.

Stack containers

A stack container is a container that lets you have several different sub-containers, where only one is visible at a time (sometimes referred to as a card layout). This layout component is particularly useful if you are creating a step-by-step wizard. Let's take a look at how you would create a Dijit stack container, complete with a stack controller to navigate between stacks.

First, create a new file from the basic Dijit template (Listing 1). In the HTML code section, add the code from Listing 16.

Listing 16. Creating a stack container and controller

<div dojoType="dijit.layout.StackContainer" id="stackContainer"> <div dojoType="dijit.layout.ContentPane" title="Stack 1"> This is the content in stack 1. </div> <div dojoType="dijit.layout.ContentPane" title="Stack 2"> This is the content in stack 2. </div></div><div dojoType="dijit.layout.StackController" containerId="stackContainer"></div>

Before you save, be sure to include the necessary dojo.require calls as required (see Listing 17).

Listing 17. Adding stack container and controller to dojo.require

dojo.require("dijit.layout.StackContainer");dojo.require("dijit.layout.StackController");dojo.require("dijit.layout.ContentPane");

Save the file and load it in your browser. You should see a result like Figure 9. Clicking on the controller buttons lets you change the currently selected stack. All of this with no JavaScript required (other than the calls to dojo.require, of course)—pretty sweet, huh?

Page 35: Dojo From the Ground Up

Figure 9. Stack container and stack controller in action

Tab containers

Like stack containers, tab containers let you have several views, with only a single view visible at a given time. However, unlike stack containers, tab containers present the options to move from each view in the form of tabs that appear above, below, or alongside the content. Furthermore, they do not require any separate controls, as they are built right into the component itself. As before, add the code in Listing 18 to the HTML section of your code.

Listing 18. Creating a tab container

<div style="width: 535px; height: 290px"> <div dojoType="dijit.layout.TabContainer" style="width: 100%; height: 100%;"> <div dojoType="dijit.layout.ContentPane" title="Tab 1"> This is the content in tab 1. </div> <div dojoType="dijit.layout.ContentPane" title="Tab 2"> This is the content in tab 2. </div> </div></div>

In this case, the tab container is wrapped in an outer <div> container, which simply defines the area the tab container can encompass. Of course, don't forget to add the relevant lines to your dojo.require block (see Listing 19).

Listing 19. Adding tab container to dojo.require

dojo.require("dijit.layout.TabContainer");dojo.require("dijit.layout.ContentPane");

Save the file and load it in your browser; the result should look like Figure 10. You can swap between views by clicking on the relevant tab.

Figure 10. Tab container in action

Page 36: Dojo From the Ground Up

Accordion containers

Yet another container that lets you display one section at a time is the accordion container. This usually takes the form of a vertical expand/collapse layout, where only one section can be open at a time, and expands to fill the entire space of the accordion container. The best way to see this is through an example, so let's go ahead and create one.

First, add the code in Listing 20 to the HTML section of your template.

Listing 20. Creating an accordion container

<div style="width: 535px; height: 290px"> <div dojoType="dijit.layout.AccordionContainer" style="width: 100%; height: 100%;"> <div dojoType="dijit.layout.ContentPane" title="Blade 1"> This is the content in blade 1. </div> <div dojoType="dijit.layout.ContentPane" title="Blade 2"> This is the content in blade 2. </div> <div dojoType="dijit.layout.ContentPane" title="Blade 3"> This is the content in blade 3. </div> </div></div>

And let's not forget your dojo.require references (see Listing 21).

Listing 21. Add accordian container to dojo.require

dojo.require("dijit.layout.AccordionContainer");dojo.require("dijit.layout.ContentPane");

Open this in your browser, and the results should be like Figure 11.

Figure 11. Accordion container in action

To switch between views, click on the title for the relevant section (or blade, as I like to call them).

BorderContainer layouts

Finally, let's look at border containers. If you have used a user interface library before, such as Swing, you might be familiar with the notion that border containers let you place components into four regions: north, south, east, and west. In Dojo, this same concept is available, but it

Page 37: Dojo From the Ground Up

is even more powerful as it can automatically provide splitters. As usual, it is best described by means of an example, so let's build one (see Listing 22).

Listing 22. Creating a border container

<div style="width: 535px; height: 290px"> <div dojoType="dijit.layout.BorderContainer" style="width: 100%; height: 100%;"> <div dojoType="dijit.layout.ContentPane" region="top" splitter="true"> This is the content in the top section. </div> <div dojoType="dijit.layout.ContentPane" region="left" style="width: 100px;" splitter="true"> This is the content in the left section. </div> <div dojoType="dijit.layout.ContentPane" region="center" splitter="true"> This is the content in the center section. </div> <div dojoType="dijit.layout.ContentPane" region="right" style="width: 100px;" splitter="true"> This is the content in the right section. </div> <div dojoType="dijit.layout.ContentPane" region="bottom" splitter="true"> This is the content in the bottom section. </div> </div></div>

Listing 22 creates a layout with a top and bottom section, and left, right, and center sections in between. Before you try it out, add the following code (see Listing 23) to your dojo.require section.

Listing 23. Adding border container to dojo.require

dojo.require("dijit.layout.BorderContainer");dojo.require("dijit.layout.ContentPane");

Fire up your browser and open the file you just saved. You should see something like the window in Figure 12.

Figure 12. Border container in action

Not only has this created a very structured layout for your application, but it is also customizable, as the user can drag the center handle on each pane and drag it to resize that particular part of the application. Pretty impressive for an application that doesn't even use JavaScript yet (except for the dojo.require calls).

Page 38: Dojo From the Ground Up

As you have seen in this section, Dijit makes it extremely easy to create advanced layouts for your applications, with no complex JavaScript code required. All of the layout components used in this section can also be created programmatically. For good examples of this, check out the Dojo documentation (see Resources).

DojoX: Dojo's bundled library of extensions

In addition to the Dojo Base, Dojo Core, and Dijit libraries, Dojo also provides support for DojoX, a set of experimental and supplementary components and features that did not make it into other parts of the framework. Reasons for this can vary from the code not being quite ready for production, to being too large to include by default, or simply that the extension is not as widely used or required as the features that are included in the main part of the Dojo toolkit. As a result, you should be careful when using DojoX components, as some of them may not be heavily tested or certified to have support for accessibility or internationalization.

DojoX includes a wide variety of additional functions. The following list is a sample of what's available in DojoX:

Audio/Video playback Charting Comet client A wide range of data stores for different data sources including CouchDB databases, CSV files, web APIs such as Flickr, Google

Search, Amazon S3, and more Vector drawing APIs Additional form widgets Data grid Image widgets (including galleries, slide shows, and lightboxes) JSON querying More layout containers RPC support Various other widgets including gauges, alternative calendars and color pickers, fish eye widgets, file pickers, ad banner rotators,

and many more

Including DojoX extensions in your application is really simple. Unlike other JavaScript libraries, where you would need to browse a repository, download additional files, upload them to your server, and reference these files in your code, DojoX works pretty much the same way as Dijit components. As always, it's easiest to show this by means of an example. Let's create a new page that has uses DojoX's Ratings form widget.

First, create a new page using your basic Dijit template from Listing 1. Below the line that includes the claro.css file near the top, add a second <link> tag for loading the rating widget CSS file: <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/dojo/1.5/dojox/form/resources/Rating.css" />.

Next, in the HTML section of the code, add the following line to add a rating control with 5 stars available, with 3 stars selected by default: <div dojoType="dojox.form.Rating" numstars="5" value="3"></div>.

Finally, where you loaded Dijit components using dojo.require earlier, add the following line: dojo.require("dojox.form.Rating");.

And you're done. Really, that's all there is to using DojoX components in your application. Of course, some of the more complex widgets (like grids and so on) may take a bit more work than this basic component, but the basic steps required are the same. The end result should look something like Figure 13.

Figure 13. DojoX rating widget in action

Page 39: Dojo From the Ground Up

For more detailed information on DojoX and all of the features it offers, see the Dojo documentation. A link to the latest version of the documentation is provided in Resources.

Conclusion

As you have learned in this article, Dojo is a lot more than just a JavaScript framework. The Dijit component library boasts a large number of easy-to-use widgets that can seriously enhance the usability of your application, saving the developer from needing to write these components from scratch. In addition, all Dijit components are completely theme-friendly, making it easy to use Dojo to build functionality that fits right in with your own applications. In this article, you learned how to use Dijit to create components declaratively and programmatically as well as how to define which theme you want to use. You also learned how to create impressive layouts with just a few lines of code. Finally, you discovered just how simple it is to add the extended features DojoX has to offer to your applications, without requiring additional plug-ins to be downloaded and configured.

Page 40: Dojo From the Ground Up

Writing Modular Javascript with DOJO

Now, before we rush out and buy this T-shirt for him, let’s recognize that Hater has a point. There is no programming language

that allows you to go from Zero to Incomprehensible quite like JavaScript (Ok fine, we’ll throw in Perl too). In academic terms,

Hater is referring to a lack of cohesion. *Blows dust off of Software Engineering book from my RIT days*.

1.. A measure of the extent to which related aspects of a system are kept together in the same module, and

unrelated aspects are kept out.

Is it possible to write highly cohesive code with JavaScript? Absolutely. And when you use Dojo, it’s incredibly easy. All you

need is dojo.provide() and dojo.require().

To demonstrate, let’s engage in one of my favorite Enterprise past-times, presenting an over-engineered example to illustrate a

simple point! We’re going to model Phone objects and provide an API to indentify the Phone based on its properties. To show

you that I take over-engineering seriously, I’ll use a UML diagram.

For those of you that don’t have a background in UML, I’ll explain what is going on here. We have a

example.smartphone.Phone class with two fields; numberOfGs, which is a number, and hasTheWiFis, which is a

boolean. The class has one method, identifyYourself(). This object has a dependency on

example.smartphone.util. The example.smartphone.util object in turn has a dependency on

example.smartphone.types, which contains string constants describing the phones in our system.

Bringing modularity to this system is straightforward. We will create a file for each of the objects, like so:

Hold on, JavaScript Hater has something to say about my file structure…

Umm, Hello? Dan, these are JavaScript files that we are talking about here. At the end of the day, each of

those files is going to be included in our page with a script element, and we definitely want to keep the number

of script elements to a minimum. And what about those dependencies?! Not only we will have to manage lots

of script elements, we’ll have to keep track of the order them in the page….and what if we add new files with

other dependencies? See?! This is why I hate JavaScript. Who cares about cohesion?! If we must use

JavaScript, let’s just throw all that code into one file and be done with it!

Page 41: Dojo From the Ground Up

As much as I hate to admit it, Hater, again, has a point. Managing JavaScript file dependencies has traditionally been a pain.

JavaScript doesn’t have built-in dependency management like some of our favorite statically typed languages. This isn’t a dire

situation though; we just need a system to manage this madness. Enter dojo.provide() and dojo.require(), true

partners in the fight against incohesive JavaScript.

Dojo Resources and Modules

In Dojo parlance, individual JavaScript files are known as resources and the folder structures that contain related resources are

called modules. In our example, Phone.js, types.js, and util.js are resources that live in a module called

example.smartphone.

Let’s take a look at types.js. Here it is in its entirety.

1 dojo.provide("example.smartphone.types");

3 example.smartphone.types.IPHONE_4 = "iPhone 4";

4 example.smartphone.types.HTC_EVO = "HTC Evo";

5example.smartphone.types.OTHER = "Whoah. I think this may be Gordon Gekko's phone in 'Wall

Street'.";

On line 1 we add a call to dojo.provide. A call to dojo.provide will be the first line in all of our resources. dojo.provide

is very similar to Java’s package system. The argument to dojo.provide is a dot-separated string that describes the

underlying file structure of the resource. In this case, our resource is located at example/smartphone/types.js. (This path

is relative to the parent folder of the dojo.js file. That is, the example folder needs to be a peer with dojo, dijit, and dojox.

When you place your modules here, Dojo will find them automatically. You can put modules in other locations, but must utilize

dojo.registerModulePath or set the modulePaths argument on the djConfig variable. For simplicity, we’ll assume the example

folder is a peer to dojo, dijit, and dojox).

Anywhere in consuming code where we want to use this resource, we use dojo.require:

1 dojo.require("example.smartphone.types");

It’s as simple as that. It’s so simple that most people don’t even begin to wonder how it works. ‘Yeah, Dojo does some magic to

load that file, cool.’ But we are not ‘most people’. At Enterprise Dojo, we recognize that Dojo is not, in fact, magic. It’s

JavaScript. We are JavaScript Scholars here, and we aren’t comfortable with dismissing API as magic. In addition,

understanding how dojo.require() and dojo.provide() work truly helps in using them effectively. So we’ll take a little

detour to dive into it.

A Deep Dive into dojo.require and dojo.provide

There are several great tutorials out there on this topic. You should read them all, but I’ll give a quick overview of what’s

happening here. When dojo.require(“example.smartphone.types”); runs, it loads and executes the JavaScript file at

example\smartphone\types.js. The first line it executes is dojo.provide(“example.smartphone.types”);. This

line creates a namespace that is modeled after the file structure of the module. Simply put, a namespace is a global variable

with nested sub-variables. In this case, dojo.provide creates a global variable called example, adds a sub-variable to it

called smartphone, and then adds a sub-variable to smartphone called types.

This screen-shot from the DOM tab of Firebug directly after calling dojo.provide(“example.smartphone.types”)

should help you understand:

Page 42: Dojo From the Ground Up

Now that we have this nice object hierarchy, we can add our constants to it using regular JavaScript notation. See

highlighted lines below:

1 dojo.provide("example.smartphone.types");

3 example.smartphone.types.IPHONE_4 = "iPhone 4";

4 example.smartphone.types.HTC_EVO = "HTC Evo";

5example.smartphone.types.OTHER = "Whoah. I think this may be Gordon Gekko's phone

in 'Wall Street'.";

Here is what it looks like in memory:

Page 43: Dojo From the Ground Up

Similarly, here is the code for util.js:

01 dojo.provide("example.smartphone.util");

03 dojo.require("example.smartphone.types");

05 example.smartphone.util.calculatePhoneType = function(phone) {

06     if(phone.numberOfGs == 3) {

07        return

example.smartphone.types.IPHONE_4;

08     } else if(phone.numberOfGs == 4) {

09        return

example.smartphone.types.HTC_EVO;

10     } else {

11        return

example.smartphone.types.OTHER;

12     }

13 };

The call to dojo.provide on line 1 adds a util variable to our existing example.smartphone namespace. On line 5 we add a

function called calculatePhoneType to the util object. Show them what I mean, Firebug:

Page 44: Dojo From the Ground Up

Adding dojo.declare Into the Mix

Lastly, let’s take a look at example.smartphone.Phone. Our two previous examples were singletons. There is no need to

have more than one instance of util or types in our system. Phone is different. It needs to be a Class so that we can

instantiate multiple instances of it. For that we will use Dojo’s mechanism of simulating Classes, dojo.declare.

The arguments to dojo.declare are the Class’s name, followed by its super types, and finally an object that contains its

properties. Here’s how we will use it to declare a Phone class. This is the entire contents of example/smartphone/Phone.js:

01 dojo.provide("example.smartphone.Phone");

03 dojo.require("example.smartphone.util");

05 dojo.declare("example.smartphone.Phone", [], {

06     numberOfGs : null,

07     hasTheWiFis : null,

08    constructor : function(numGs, wiFis)

{

09        this.numberOfGs =

numGs;

10        this.hasTheWiFis =

wiFis;

11     },

12    identifyYourSelf : function()

{

Page 45: Dojo From the Ground Up

13        return

example.smartphone.util.calculatePhoneType(this);

14     }

15 });

Walking through this code, the dojo.provide in line 1 sets up our namespace, adding a simple object named ‘Phone’ onto the

example.smartphone namespace. Line 3 specifies our dependency on example.smartphone.util, and Line 5 does the

job of declaring our Phone class. Notice how our class name is the same as what we passed to dojo.provide. When the

dojo.declare runs, the Phone object in memory is replaced by a constructor function that we use to instantiate Phone

objects. These Firebug captures illustrate what I mean:

Right after dojo.provide(‘example.smartphone.Phone’):

After dojo.declare(‘example.smartphone.Phone’):

Page 46: Dojo From the Ground Up

This is a little confusing. You may be wondering what would have happened if we chose to name our Class something other

than example.smartphone.Phone. Or what if we had more than one dojo.declare in our resource? The answer is that

dojo.declare will indiscriminately create new namespaces for any of these scenarios. If we added

dojo.declare(“some.other.namespace”, …) to the end of Phone.js, we’d end up with this:

Page 47: Dojo From the Ground Up

The practice of dojo.declare’ing a class with the same name as the resource in which it is declared is simply a pattern for

neatly organizing our code, and is used extensively by Dojo internally. I haven’t even scratched the surface of dojo.declare.

It enables inheritance and all sorts of other Object Oriented goodness. Read the details here.

Wrapping Things Up

We now have every piece of our system implemented, all neatly packaged, maintaining the highest level of cohesion. Professor Lutz would be so proud. And we owe it all to dojo.require and

dojo.provide. Nice work guys.

1 dojo.require("example.smartphone.Phone");

3 var phone1 = new example.smartphone.Phone(3, true);

4 var phone2 = new example.smartphone.Phone(4, true);

5 var phone3 = new example.smartphone.Phone(2, false);

7 console.log("Phone 1 is: " + phone1.identifyYourSelf());

8 console.log("Phone 2 is: " + phone2.identifyYourSelf());

9 console.log("Phone 3 is: " + phone3.identifyYourSelf());

Output from Firebug’s console:

Page 48: Dojo From the Ground Up

Did you notice how we only had to call dojo.require on example.smartphone.Phone and not any of the other objects in

our system? That’s not a typo. Because our objects specify their dependencies internally via calls to dojo.require, the

dependent resources are loaded automatically. Now that is how you MANAGE DEPENDENCIES!!! Sorry, I get excited about

this stuff.

That may have seemed like a lot of work to get something simple going, and admittedly the benefits to structuring your code this

way are not glaringly obvious from this example. But when your real-world JavaScript application grows, and it will, you may

have hundreds of resources with seriously complex dependencies. In these types of systems, cohesion and dependency

management are not only helpful, they are absolutely essential.

You may also have performance concerns due to the costly time that it takes to load multiple JavaScript files. This is addressed

by the Dojo Build System, the details of which are a post for another day.

If you’d like to play around with the source code presented in this post, download this zip file.

Page 49: Dojo From the Ground Up

Programmers are drawn to Dojo for its incredible suite of user interface widgets, better known as Dijits. If you are not familiar

with the breadth of Dijits that are available the Theme Tester is a good place to have a look around. Any doubts that you have

about whether Dojo provides a suitable suite of widgets for your web application should go away quickly after playing with the

Theme Tester for a few minutes. Another invaluable resource is the Dijit Reference Guide on dojotoolkit.org that shows

examples of all of the widgets in the Dijit library.

Custom Dojo Widgets

Often lost in the shuffle is that you can write your own custom widgets in addition to using the off-the-shelf Dijits. Enterprise Web

Applications are full of common UI elements and functionality that are ripe to be encapsulated into a reusable widget. Lucky for

you, Dojo makes this process easy. The resulting code is cohesive and modular, just the way we like it.

Let’s build a simple Dojo Widget using some best practices. Now, if this were an ordinary Enterprise-y blog, our example widget

would be some kind of ‘business card’ that showed the details of a corporate employee. But let’s be honest, corporate

employees are boring. We will build a business card widget for a much cooler class of people. Who are the coolest people in the

world? That’s right, high school students!

Building a High School Student Widget

Our widget will show a picture of a high school student and their pertinent details. I don’t know many high school students, so

acquiring photographs for use in this demonstration proved challenging. It was really weird, these kids acted downright

frightened when I approached them in the mall and asked if they wanted to be in a JavaScript blog. Youth these days! To solve

this problem, I spoke with a renowned social anthropologist who explained to me that High School students can be classified

into exactly three groups: Emo, Punk, and Geek.

Our finished product will look something like this 1998-era version of your author:

NameDan Lee

GradeSenior

HeroLinus Torvalds

Widget Pieces

A typical Dojo Widget is comprised of three files:

A JavaScript file that declares the widget and defines its logic.

An HTML fragment file that declares the widget’s semantic markup.

A CSS file that defines the widget’s styling information.

These files don’t have to be placed in any particular location, but we will use the same convention that Dojo uses for its widgets

and set up a directory structure like this:

Our widget will be called widgets.HighSchooler, and its JavaScript file will be placed in a corresponding resource located at

widgets/HighSchooler.js. (If you read my previous post about writing modular JavaScript with Dojo, this will look familiar). Our

Page 50: Dojo From the Ground Up

HTML fragment will live in a folder called templates and our CSS file will live in a folder called themes ,with a sub-directory

called highschool. The images will also be placed in the themes directory.

The JavaScript File

Let’s take a look at a stubbed version of our widget’s JavaScript file.

01 dojo.provide("widgets.HighSchooler");

02   

03 dojo.require("dijit._Widget");

04 dojo.require("dijit._Templated");

06 dojo.declare("widgets.HighSchooler", [ dijit._Widget, dijit._Templated ], {

07     templateString : dojo.cache("widgets",

08                                "templates/

HighSchooler.html"),

09     name : "",

10    grade :

"",

11     hero : "",

12    stereotype :

""

13 });

Declaring a widget is straight-forward. We use dojo.provide to declare our namespace, use dojo.require to load the

necessary dependencies, and then use dojo.declare for the actual widget definition. The first argument to dojo.declare is

our widget’s name. We are using the pattern of giving our widget the same name as our namespace. The second argument is

the widget’s super types. Dojo Widgets typically define two super types, dijit._Widget and dijit._Templated. _Widget

provides our widget with necessary life-cycle methods, which we will soon explore. _Templated provides support for

instantiating our widget from an HTML template.

The rest of the JavaScript defines the properties and methods for our HighSchooler widget. templateString is a special

property that indicates where to find the HTML template file. The rest of the properties represent the meaningful fields of our

HighSchooler.

The CSS File

01 .highSchooler {

02    border:1px solid

#CCCCCC;

03    height:165px;

04     margin: 10px;

05 }

06   

07 .highSchooler .profile {

08     list-style:none outside

none;

09     font: 1.3em 'Lucida Grande',sans-

serif;

10 }

Page 51: Dojo From the Ground Up

12 .highSchooler .avatar {

13     float: left;

14    margin:5px 30px 5px

10px;

15 }

16   

17 .highSchooler .profile .label {

18     font-weight: bold;

19    padding-right:

5px;

20 }

Nothing special here, just some styles that our widget will use. The interesting thing here is that all styling information about the

widget is encapsulated into this file. If we were clever about our styling information it would be possible to implement a skinnable

widget, as Dojo does with the Dijit library. (This is beyond the scope of this exercise though, our widget’s styling is rudimentary).

The HTML Template

This file contains the actual HTML markup of our widget. In this case, we define a div that contains an image

element for the avatar and another div that contains an unordered list to display the details of our HighSchooler.

Notice that the relevant CSS classes are set on the nodes of this HTML fragment.

01 <div class="highSchooler">

02   <div class="avatar">

03    <img></

img>

04   </div>

05   <div>

06    <ul

class="profile">

07       <li><span class="label">Name</span><span></span></li>

08      <li><span

class="label">Grade</span><span></span></li>

09      <li><span

class="label">Hero</span><span></span></li>

10     </ul>

11   </div>

12 </div>

Using dojoAttachPoint

There are certain elements in the widget that we will want to manipulate with JavaScript. In this case the elements of interest are

the image tag that shows the avatar and the span elements next to the Name, Grade, and Hero labels. We’ll use an extremely

cool feature of Dojo called dojoattachpoint to enable these elements to be programmatically manipulated. We’ll add

dojoattachpoint attributes to each of the elements that we would like to manipulate like so:

01 <div class="highSchooler">

02   <div class="avatar">

Page 52: Dojo From the Ground Up

03    <img

dojoattachpoint="imageNode"></img>

04   </div>

05   <div>

06    <ul

class="profile">

07       <li><span class="label">Name</span>

08        <span

dojoattachpoint="nameNode"></span>

09       </li>

10      <li><span

class="label">Grade</span>

11        <span

dojoattachpoint="gradeNode"></span>

12       </li>

13       <li><span class="label">Hero</span>

14          <span

dojoattachpoint="heroNode"></span>

15      </

li>

16     </ul>

17   </div>

18 </div>

By adding dojoattachpoint, we have provided access to these DOM nodes in the widget’s JavaScript file. A property is

dynamically added to the instance of the widget whose value is the DOM node associated with the element with the

dojoattachpoint attribute. The name of this property is the value of the dojoattachpoint attribute. For example, if we want to set

the innerHTML of the ‘Name’ span to correspond to our widget’s fullName property, we can do so in the widget’s JavaScript

file like this:

1 this.nameNode.innerHTML = this.fullName;

The rest of our widget’s DOM manipulation code follows this same pattern. One thing to point out is that we only want this code

to run after the widget’s DOM is ready. Dojo provides lifecycle methods that get called during a widget’s initialization. The

lifecycle method where it is safe to make DOM manipulations is called postCreate. We’ll add a postCreate function to our widget

that sets up each of the span elements and sets the image to the appropriate avatar based on the stereotype property:

01 postCreate : function() {

02    this.nameNode.innerHTML =

this.fullName;

03    this.gradeNode.innerHTML =

this.grade;

04     this.heroNode.innerHTML = this.hero;

05     var keys = {

06            emo :

"emo.png",

07             geek :

Page 53: Dojo From the Ground Up

"geek.png",

08            punk:

"punk.png"

09     };

10    var key = keys[this.stereotype] ||

"na.png";

11     var imagePath = dojo.moduleUrl("widgets",

12            "themes/highschool/images/" +

key).toString();

13    dojo.attr(this.imageNode, "src", imagePath);

14 }

That’s it! Our widget’s JavaScript is done. Here it is in its entirety with some helpful comments.

01 // dojo.provide allows pages to use all of the

02 // types declared in this resource.

03 dojo.provide("widgets.HighSchooler");

05 // dojo.require the necessary dijit hierarchy

06 dojo.require("dijit._Widget");

07 dojo.require("dijit._Templated");

09 dojo.declare("widgets.HighSchooler", [ dijit._Widget,

10         dijit._Templated ], {

11     // Path to the template

12    templateString :

dojo.cache("widgets",

13            "templates/

HighSchooler.html"),

15    // Widget

properties

16     fullName : "",

17    grade :

"",

18     hero : "",

19    stereotype :

"",

21    // Manipulate the widget's DOM, when

ready

22     postCreate : function() {

23        // Using the attributes defined via

dojoattachpoint

24         this.nameNode.innerHTML = this.fullName;

25        this.gradeNode.innerHTML =

this.grade;

26         this.heroNode.innerHTML = this.hero;

28         // Setting the avatar to be the appropriate

Page 54: Dojo From the Ground Up

image

29         var keys = {

30            emo :

"emo.png",

31            geek :

"geek.png",

32            punk :

"punk.png"

33         };

34        var key = keys[this.stereotype] ||

"na.png";

35         var imagePath = dojo.moduleUrl("widgets",

36                "themes/highschool/images/" +

key).toString();

38         // Set the 'src' attribute on our <img>

39        dojo.attr(this.imageNode, "src", imagePath);

40     }

41 });

Programmatic Widget Creation

OK, we’ve got everything defined. The question is, how do we get these bad-boys into a page? There are two ways to

instantiate a Dojo Widget, programmatic and declarative. We’ll look at programmatic creation first. To create an instance of a

widget, you simply ‘new’ it up. Optionally you can pass the ID of a node in your page where you would like the widget to appear.

Alternatively, you can use the widget’s placeAt function if you need more finely grained control of where it shows up.

01 // Always dojo.require the resources that will be used

02 dojo.require("widgets.HighSchooler");

03   

04 // Widget instances are almost always created inside a 'ready'

05 // block, as they represent DOM manipulation

06 dojo.ready(function() {

07    // Replace the contents of the node with ID

'nodeId'

08    // with our widget

09    var kalEl = new

widgets.HighSchooler({

10         fullName:"Clark Kent",

11         grade:"Senior",

12        stereotype:"geek",

13        hero:"Myself?"},

"nodeId");

14   

15    // Place our widget at the end of the node with ID

'nodeId'

Page 55: Dojo From the Ground Up

16     var kalEl = new widgets.HighSchooler({

17        fullName:"Clark

Kent",

18         grade:"Senior",

19        stereotype:"geek",

20        hero:"Myself?"});

21 kalEl.placeAt("nodeId", "last");

22   

23 });

The literal object that we pass in the constructor corresponds directly to the properties of our widget. Dojo takes care of

initializing them for us. Slick!

Programmatic Widget Creation In Action!

Here’s a little demonstration of programmatic widget creation. I used Dojo to bind an event to the button that uses the

value in the combo to programmatically create a new widget and add it to the end of the node below. When the button

is clicked, this code is run. Try it out. Making Geeks is fun!

1 // Get the value from the combo

2 var typeOfTeen = dijit.byId('highSchoolerSelect').attr('value');

3 var newHighSchooler = new widgets.HighSchooler({

4     fullName : "I was",

5     grade : "created",

6    stereotype :

typeOfTeen,

7    hero :

"programatically"});

8   

9 newHighSchooler.placeAt("teensGoHere", "last");Emo ▼

●Create High Schooler!

Declarative Widget Creation

Sometimes it is more convenient to specify a widget in markup. Using markup is also a fantastic way to quickly prototype your

widget as you are developing it. Dojo provides the dojoType attribute to facilitate this. To declare a widget using markup, you

simply specify the type-name of the widget using the dojoType attribute, and then specify any widget properties using

attributes of their own. So if we wanted to declare a punk named Chris Jaun who’s hero is Bill Bradley, we’d do it

like this.

1 <div dojotype="widgets.HighSchooler"

2        fullName="Chris Jaun"

3        grade="Senior"

4        stereotype="punk

Page 56: Dojo From the Ground Up

"

5       hero="Bill

Bradley">

6 </div>

Which would get rendered like this.

NameChris Jaun

GradeSenior

HeroBill Bradley

(For all of you XHTML purists out there, dojoType is being deprecated in Dojo 1.6 in favor of HTML5′s data-* mechanism.

Hooray for clean W3C validation scans!)

One thing to point out about declaring widget’s using markup is that in order to get Dojo to automatically parse the page for

them, you have to set the parseOnLoad attribute to true in Dojo’s djConfig configuration variable.

Conclusion

Like most Dojo features, custom widgets are an incredibly powerful mechanism that would be impossible to fully cover in a

single blog post. As such, expect many future Enterprise Dojo posts about this topic. I hope that this post piqued your attention

and that you are now hungry to learn more. Check out this article in on dojotoolkit.org for a more detailed look at writing your

own widgets.

As your web application requirements get more mature, separating and organizing your presentation layer is critical. Custom

Dojo widgets enable us to create modular, reusable user interface components, something that every enterprise-caliber web

application needs.