Object-oriented JavaScript programming for Java developers reWeb 2.0 has brought with it the need to develop extensive JavaScript infrastructure code on the client side, something few Java developers saw themselves doing five years ago. The open source Dojo toolkit distinguishes itself from other JavaScript libraries with capabilities that go far beyond simplifying DOM access. In this first half of his introduction to Dojo, Sunil Patil introduces the toolkit’s basic features, helps you set up your development and debugging environment, and shows you how to put Dojo’s mojo to work in your Ajax development projects. Level: Intermediate In the Web 1.0 world, the common Java application architecture called for implementing business and application flow logic with Java EE on the server side. Web application developers typically used JavaScript only for input validation and to display error messages to users. Accordingly, most Web 1.0 applications used some kind of Model-View-Controller (MVC) framework — such as Struts, JavaServer Faces (JSF), or Spring MVC — on the server side, but few needed a JavaScript framework for client-side programming. Web 2.0 has ushered in a very different programming model, where much of the application flow and business logic is developed using JavaScript on the client side. We commonly use JavaScript code for tasks such as: Making asynchronous requests to the server side Document object model (DOM) manipulation and event-handling logic that works across multiple browsers Internationalization Logging You can either write and maintain this infrastructure code on your own or take the less painful route of using a JavaScript library. One of the more capable entries in this space is the Dojo toolkit, an open source JavaScript framework that you can use to create free or commercial applications. This article introduces you to Dojo’s core features and widget library; walks you through installing and setting up a JavaScript development and debugging environment (using Dojo and Firebug); and gets you started with building a sample application using Dojo. You’ll also learn about Dojo’s support for object-oriented programming in JavaScript (which is based on familiar concepts such as classes, constructors, and inheritance), and get a quick introduction to Dojo modules. Dojo at a glance There currently are quite a few open source and commercial JavaScript frameworks available, including Prototype, EXTJS, YUI, and jQuery. Whereas most JavaScript frameworks focus on simplifying DOM access, it could be argued that Dojo is a one-stop solution. Here is some of what Dojo does for you: Introduces the concept of classes, constructors, and inheritance in JavaScript, allowing you to build object-oriented JavaScript code. Allows you to build more-manageable code by breaking your code into modules. Simplifies Ajax programming by providing infrastructure code for making asynchronous requests using XMLHttpRequest and cross-browser-compatible DOM-manipulation code. As a framework, Dojo has three main components: The Dojo core provides core functionality such as ability to make remote method calls, manipulate DOM node, and manipulate Cascading Style Sheets (CSS). The Dojo core also supports animation features and drag-and-drop functionality. Dijit is Dojo’s widget library, built on top of the Dojo core. Dijit provides template-based, accessible widgets, not only for simple form control but also advanced widgets such as calendar control, menus, toolbars, progress bars, charts, and graphs. DojoX is a container for developing extensions to the Dojo toolkit. It acts as an incubator for new ideas and a testbed for experimental additions to the main toolkit, as well as a repository for more stable and mature extensions. Dojo’s history Alex Russell, David Schontzler, and Dylan Schieman started work on the Dojo framework by in 2004 while working for Informatica. Later many other developers started contributing to Dojo. In 2005, the Dojo foundation was formed to house the code and manage intellectual-property rights. So far, eight major releases have been issued, and the framework has been downloaded more than 1 million times. Companies such as IBM, AOL, Sun, SitePen, Blogline, Google, Nextweb, and others contribute to the Dojo framework. Setting up your development environment Before you can start developing this article’s sample Dojo application, you need to set up your development and debug environment so that you can try out application changes rapidly and debug issues if errors occur. Setting up a development environment for a JavaScript framework like Dojo is a little different from doing so for Java SE or EE frameworks. You must first install the Dojo framework in your Web application and then set up the debugging environment in the browser. Installing the Dojo toolkit The Dojo toolkit depends on set of JavaScript, CSS, and HTML files to be available in a predefined directory structure at runtime. You can install Dojo in one of three ways: Use Dojo from a content-delivery network (CDN): The easiest way to install Dojo is to use an instance that is available on a CDN near you. For example, you can install the 1.2 version of Dojo by including one of two script tags on your page: Points to AOL’s CDN: <SCRIPT TYPE="text/JavaScript" SRC="http://o.aolcdn.com/dojo/1.2/dojo/dojo.xd.js"/> Points to Google’s CDN: <SCRIPT TYPE="text/JavaScript"> SRC="http://ajax.googleapis.com/ajax/libs/dojo/1.2/dojo/dojo.xd.js"/> Install Dojo on your server: First, download the latest Dojo release. Once you have the release .zip file, you can unzip it on your Web server so that all your Web applications can use it. Or, if prefer to have a separate version of Dojo for each of your Web applications, then you can unzip the Dojo .zip files in one of the WebContent subdirectories, such as the js folder, of your Java EE Web application. Now you can use Dojo by including this script tag in your Web page: <SCRIPT TYPE="text/JavaScript" SRC="js/dojo/dojo.js"/> When you download the Dojo binaries, you can get either the source or release version. You should always use the release version in your production environment because it is compressed and optimized for faster download. You can use the source version in your development environment if you want to debug Dojo to learn how it works under the hood. Install the latest development build on your server: Download the nightly Dojo release, then follow the post-download steps in option 2 above. Note that this approach is only for advanced users, and you should have a compelling reason to choose it. The Dojo framework code is split into multiple files, but once dojo.js is loaded it will automatically download all necessary remaining files. You can verify that Dojo is installed correctly by accessing <BASEURL>/js/dijit/themes/themeTester.html. This URL opens an HTML page displaying various Dijit widgets. Setting up your debug environment Firebug is an open source debugging extension for Firefox. It provides tools for debugging JavaScript, CSS, and HTML. Firebug Lite lets you simulate Firebug functionality in other browsers such as Internet Explorer, Opera, and Safari. Firebug does the following: Allows you to debug and profile JavaScript. Provides a log4j-like JavaScript logging framework. Monitors the time that it takes to download resources such as .js, .css, and image files. It can be used to monitor XMLHttpRequests and responses. Lets you inspect and edit the live HTML generated by JavaScript. Displays all the CSS styles on the page and allows you to try out your changes online without a page refresh. I strongly recommended that you use Firefox wtih Firebug during the development phase. Dojo takes care of cross-browser compatibility issues, so code that works in Firefox should also work in other browsers. Developing a Hello World application Once you’ve set up your development and debug environment, you’re ready to try building a sample “Hello World” application using Dojo. The simplest way to do this would be to set up an HTTP server, create a static HTML page, and use Dojo in that page. Alternately, you could create a dynamic HTML page using the technology of your choice, such as Java EE, PHP, or .NET. For this exercise we’ll create a Java EE Web application. Hear this: Nate Shutta on tools for Ajax Foundations of Ajax co-author Nate Shutta talks about JavaScript libraries, debuggers, and frameworks in a JavaWorld podcast with Andrew Glover. Listen now! You can use your IDE of choice to create the HelloDojo Web application. Or you can use a text editor and a build script that allows you to package your code in a .war file. I developed the sample code using the Eclipse IDE for Java EE Developers, which provides tools for creating dynamic Web applications and for deploying application code on the Apache Tomcat server from within the IDE. It allows you to try out your changes rapidly. Follow these steps to create the Hello World sample application: Download dojo-release-1.2.3.tar.gz from the Dojo Download site. Unzip dojo-release-1.2.3.tar.gz in the workspaceroot/HelloDojo/WebContent/js folder. Create an index.html page (shown in Listing 1) in the workspaceroot/HelloDojo/WebContent folder. Listing 1. The index.html file <html> <head> <title>Hello World</title> <script type="text/JavaScript" src="js/dojo/dojo.js" djConfig="parseOnLoad: true"> </script> <style type="text/css"> @import "js/dijit/themes/tundra/tundra.css"; @import "js/dojo/resources/dojo.css"; </style> <script type="text/JavaScript"> dojo.require("dijit.form.Button"); </script> </head> <body class="tundra"> <button dojoType="dijit.form.Button" id="helloButton"> Hello World <script type="dojo/method" event="onClick"> alert("Hello Dojo."); </script> </button> </body> </html> The index.html file is a simple HTML document that generates one button using the dijit.form.button widget. When you click on that button the application displays “Hello Dojo” in an alert message. Lets take a closer look at each of these elements: The dojo.js file is the main component in the Dojo toolkit. You can use Dojo by including this file in your page: <script type="text/JavaScript" src="js/dojo/dojo.js" djConfig="parseOnLoad: true"> </script> In the sample code, we want to use the Dojo framework .js files that are unzipped in the Web application’s WebContent/js folder, so you must use the js/dojo/dojo.js path. The djConfig attribute is used for configuring the Dojo runtime, which I’ll talk about more in the next section. We want to use Dijit’s button widget, so you must include the Dijit style sheet, as shown here: <style type="text/css"> @import "js/dijit/themes/tundra/tundra.css"; </style> Dijit allows you to choose a theme to use. The default theme is tundra , which we use in our sample code by including tundra.css in index.html . Dojo uses the concept of modules, which are similar to Java packages. (I’ll provide more detail about modules later in this article.) Before you use functionality from a particular package, you must include that package in your page. The dojo.require() call — similar to Java’s import statement — is used for importing a Dojo module: <script type="text/JavaScript"> dojo.require("dijit.form.Button"); </script> The line dojo.require("dijit.form.Button") tells Dojo to load the dijit.form.Button class on your page. You can use a Dijit widget by using the same markup as that of the normal HTML element. The only difference is that you must add the dojoType attribute indicating name of the Dijit widget that you want to use: <button dojoType="dijit.form.Button" id="helloButton"> Hello World <script type="dojo/method" event="onClick"> alert("Hello Dojo."); </script> </button> You want to generate a button based on the Dijit button widget, so this code adds the dojoType="dijit.form.Button" attribute to the HTML button element. Dojo also allows you to attach event handlers in a convenient way by declaring them inline. If you don’t feel comfortable with this convention you can declare a function in a script element and specify its name as a value of the onClick attribute. Next, change the web.xml file for your Web application to set index.html as the application’s default page: <?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>HelloDojo</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app> Deploy the HelloDojo Web application on your application server. If you use Eclipse and Apache Tomcat, then you can just right-click your HelloDojo project and select Execute on server to install the HelloDojo Web application on Tomcat. Once the Web application is deployed and started, try accessing it using the application-server-specific URL. If you deployed your application on Tomcat, you can access it at http://localhost:8080/HelloDojo. If you go to the Net tab, you will notice that your one request to HelloDojo is resulting in quite a few requests for additional resources such as .js, .css, and .html files. All the resources are requested from the same location where dojo.js resides. Configuring the Dojo runtime Dojo allows you to configure the runtime using the djConfig object. The default values of djConfig options are okay for most cases, but you might want to change them to enable debugging, for example, or to inform Dojo that you want to use the Dijit widget library. (It can check if any of the form controls has a dojoType attribute and if it does it will convert the control to a Dijit widget.) I’ll explain ways to configure the djConfig object and discuss what each of the various configuration options means. Configuring djConfig Dojo creates the djConfig object when the framework initializes — that is, when Dojo.js loads. If you want to make any changes in djConfig, you should do so before dojo.js is loaded. Any changes that you make in djConfig are ignored after dojo.js is loaded. You can configure the djConfig object in one of three ways: The easiest and most commonly used approach is to add the djConfig attribute to the <script> element that refers to dojo.js: <script type="text/JavaScript" src="js/dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true" /script> The djConfig attribute’s value is a comma-separated list of name/value pairs. The name is the name of the attribute; the value is the value that you want to set. If you need to set lots of attributes in the djConfig object or prefer not to use Dojo’s nonstandard attributes, you can create the djConfig object explicitly before the main dojo.js library included in the document: <script type="text/JavaScript"> var djConfig = { parseOnLoad: true, isDebug: true, locale: 'en-us', extraLocale: ['jp-jp'] }; </script> <script type="text/JavaScript" src="js/dojo/dojo.js" /> This example creates a djConfig hashmap before dojo.js gets included in the page. You can include djConfig in the Dojo Toolbox builder. When creating a custom build you include the djConfig object into the build via the scopeDjConfig parameter. See the online Dojo documentation on “The package system and custom builds” for further information on custom builds. While developing your Web application, you might want to create a separate include file that contains logic to create djConfig using one of these methods and has a dojo.js script tag. You’d then include that file in every page. The benefit is that you can change the Dojo configuration for the entire application — for example, to enable debugging — by changing the one include file. Configuration options The djConfig object provides quite a few configuration options. So far our sample code has used two of them: isDebug and parseOnLoad. Let’s take a closer look at all of the djConfig options: isDebug: This flag turns debugging on or off. Its default value is false. When you turn this flag on, Firefox generates extended debugging information in Firebug. If you’re using some other browser, it includes the Firebug Lite script files in the page and starts displaying the Firebug Lite console. debugAtAllCosts: When you use dojo.require() to declare dependency, it makes an asynchronous call to load the necessary resources and also makes sure that the resource is not loaded twice. This is approach is efficient but has a downside: when there is an error in the loaded resource — for example, in one of the classes — Firebug shows an incorrect line number for the error. When you turn the debugAtAllCosts flag to true, it includes a <script> tag in the page markup for each resource instead of loading them asynchronously. Once the resources are loaded using the <script> tag, Firebug shows the .js file name where the error occurred along with the line number for that error, which makes debugging your code easier. Don’t use this option in a production environment, because it adds a lot of overhead debugContainerId: When this option is set, Dojo searches the document’s DOM for an element with the specified ID and puts the Firebug Lite console inside that element. locale: Dojo simplifies internationalization by providing an infrastructure for loading localized resources in the page. By default it uses the locale of the user agent, but you can override that by setting the locale option. extraLocale: This option, which has no default value, specifies additional locales whose resources should also be loaded alongside the default locale when calls to dojo.requireLocalization() are processed. baseUrl: Dojo downloads required .js files on demand. By default it downloads the dependencies from the same location that dojo.js was downloaded from. If you want to change this for some reason, set the baseUrl property to the location from which the dependency .js files should be downloaded. modulePaths: You can extend the Dojo framework by creating your own classes and putting them under a custom directory structure. When you do that, you must map the namespace name to directory name so that dojo.require() can find it. Setting the modulePaths option allows you to map the namespace to the directory name. (I’ll talk more about this later in this article.). afterOnLoad: This option indicates that Dojo was added to the page after the page load. In this case Dojo doesn’t wait for the page DOMContentLoad/load events and fires its dojo.addOnLoad callbacks after making sure all outstanding dojo.required modules have loaded. parseOnLoad: Dojo has an HTML parser that parses the document’s DOM structure to find the nodes with dojoType attribute and convert them into Dojo widgets. When you set the parseOnLoad flag’s value to true, Dojo parses the DOM document on loading and converts the nodes to Dijit widgets. addOnLoad: You can set name of a function or an array of names of the functions that should be called once the page is loaded. Object-oriented JavaScript One of the lesser-known facts about JavaScript is that it is an object-oriented language. However, it is a prototype-based object-oriented language that doesn’t have the same structure as class-based languages such as Java. This can be a hard adjustment for new JavaScript programmers. Dojo provides functionality to simulate class-based object-oriented concepts such as declaring classes, constructors, and inheritance. In the background, it takes care of things like prototyping, inheritance, and various procedures that JavaScript requires. In the next sections I’ll introduce you to Dojo’s support for object-oriented programming with JavaScript. Working with classes Dojo provides a dojo.declare() method that you should use to declare a new class. It accepts the following arguments: A string representing the name of the class that you want to declare. The name of the superclass or array of names of the superclasses that you want this class to inherit from. (I’ll talk more about multiple inheritance later.) A hashmap of properties for the class. The properties represent both instance variables and member function of this class. Listing 2, for example, declares a custom.javaworld.Worker class: Listing 2. Declaring a class dojo.declare("custom.javaworld.Worker",null,{ firstName: "", lastName: "", work: function(){ console.log("Working"); } }); var johnDoe = new custom.javaworld.Worker(); johnDoe.work(); johnDoe.lastName ="Doe"; console.log("Last Name " + johnDoePerson.lastName); In Listing 2, the dojo.declare() method’s first argument is custom.javaworld.Worker — the name of the class we want to declare. The method’s second argument is null because we don’t want to inherit this class from any other class. The third argument is a hashmap, in which work is the property’s name and its value is a function. We thereby define a work() member function for the Worker class. Once the custom.javaworld.Worker class is declared, you can create a new object instance of it by calling new custom.javaworld.Worker(). Then you can start calling the new object’s methods or assign values to its member variables. Constructors A constructor allows you to initialize every object of a class by executing code whenever a new instance of the class is created. Listing 3 changes our custom.javaworld.Worker class to add a constructor. Listing 3. Adding a constructor dojo.declare("custom.javaworld.Worker",null,{ firstName: "", lastName: "", constructor: function(fName, lName){ console.debug("Constructor of com.javaworld.Worker called"); this.firstName = fName; this.lastName = lName; }, work: function(){ console.log("Working"); } }); var johnDoe = new com.javaworld.Worker("John","Doe"); console.log("First Name " + johnDoePerson.firstName); console.log("Last Name " + johnDoePerson.lastName); As you can see, we made one change in the custom.javaworld.Worker class to add a constructor member function. The constructor member function is special. It gets called whenever you create new instance of the class using the JavaScript’s new operator. The constructor takes two arguments — fName and lName — and assigns these value to the member variables, which you access by using the this operator inside the class. Inheritance The ability to extend other classes is one of the basic features of object-oriented programming. Dojo handles all the requirements for setting up an inheritance chain. For example, when you create an instance of a class, Dojo calls the constructor of its superclass before calling constructor of the child class. Also, if you add a method to the child class with same name as that of the superclass, then the method in the child class overrides the method in the superclass. Listing 4 creates a custom.javaworld.ITWorker class that extends custom.javaworld.Worker. Listing 4. Extending a class dojo.declare("custom.javaworld.ITWorker",custom.javaworld.Worker,{ constructor: function(fName, lName){ console.debug("Constructor of com.javaworld.ITWorker"); }, work: function(){ this.inherited(arguments); console.log("Writing Code"); } }); var johnDoe = new com.javaworld.ITWorker("John","Doe"); johnDoe.work(); Because we want ITWorker to extend the Worker class, Listing 4 passes the custom.javaworld.Worker class as the second argument when declaring the ITWorker class. Now when you create a new instance of ITWorker using the new operator, Dojo first invokes the constructor of Worker class. Also, the ITWorker class’s work() method overrides the Worker class’s work() method. Suppose you need to invoke the overridden method of superclass first and then add some functionality in the child class method. In that case then you can use the.inherited() construct to invoke an inherited method of the superclass. In Listing 4, when you call the ITWorker class’s work() method, it first invokes the Worker class’s work() method, which prints “Working” on the console then prints “Writing Code” on the console. Multiple inheritance Dojo allows a class to inherit from multiple classes. Listing 5 creates a PartTimeMusician class that inherits from both ITWorker and Musician. Listing 5. Inheriting from multiple classes dojo.declare("com.javaworld.Musician",null,{ constructor: function(fName, lName){ console.debug("Constructor of com.javaworld.Musician"); }, playMusic: function(){ console.log("Playing Music"); } }); dojo.declare("com.javaworld.PartTimeMusician",[com.javaworld.ITWorker,com.javaworld.Musician],{ constructor: function(fName, lName){ console.debug("Constructor of com.javaworld.PartTimeMusician"); } }); var johnDoe = new com.javaworld.PartTimeMusician("John","Doe"); johnDoe.work(); johnDoe.playMusic(); In Listing 5, we pass an array of ITWorker and Musician as the second argument to the dojo.declare() method while declaring the PartTimeMusician class. Now when you execute this code it will generate output like this: Constructor of com.javaworld.Worker called Constructor of com.javaworld.ITWorker Constructor of com.javaworld.Musician Constructor of com.javaworld.PartTimeMusician Working Writing Code Playing Music As you can see, the constructor of the Worker class, which is the parent of the ITWorker class, is invoked first, followed by the constructor of ITWorker. The constructor of ITWorker is called before Musician‘s constructor because, while declaring the PartTimeMusician class, we passed an array of superclasses in which ITWorker was the first argument and Musician was the second argument. Dojo modules As your client code grows, it gets harder to keep all the functions and global variables from using the same names and wrecking one another. To solve this problem, Dojo introduces the concept of modules. Modules, similar to Java packages, allow you to divide the client-side code into different namespaces. Our Hello World application uses modules. Everytime you call dojo.require(), Dojo loads one .js file into its own namespace. For example, when we invoke dojo.require("dijit.form.Button"), Dojo looks for a dijit/form/Button.js file under the Dojo root and loads it. Note that dojo.require() cannot load your code into different namespaces. It’s the developer’s responsibility to use namespaces in the code when creating modules. For example, the developer of dijit.form.Button took care of namespacing the code correctly. The Dojo framework code is divided into three namespaces — dojo, dijit, and dojox — that correspond to the three namespaces under the Dojo root. One module can represent either one class or a set of functions. For example, the dojo.string module represents a set of functions. Working with modules In the preceding section we developed the Worker class hierarchy by developing all the script code in index.html. But now we want to use the Worker class on multiple pages, so we will externalize Worker in a separate module by following these steps: Create a custom/javaworld directory under the Dojo root, which is the WebContent/js folder in our case. It is always a good idea to keep your code in separate directory. Create the WebContent/js/custom/javaworld/Worker.js file. Move your definition of the Worker, ITWorker, Musician, and PartTimeMusician classes to the Worker.js file. Add dojo.provide("custom.javaworld.Worker") at the top of Worker.js file: dojo.provide("custom.javaworld.Worker"); dojo.declare("custom.javaworld.Worker",null, //Rest of the code to declare Worker, Musician, ITWorker and PartTimeMusician classes Each Dojo JavaScript source file must have at least one dojo.provide() call at the top of the file, corresponding to the file name. For example, our sample dojoroot /custom/javaworld/Worker.js file should have dojo.provide("custom.javaworld.Worker") at the top. When the browser loads Worker.js , the dojo.provide() call registers that it has been loaded. Once the Worker class definition is moved to its own module, you must make this change in index.html to use it: dojo.require("custom.javaworld.Worker"); var johnDoe = new custom.javaworld.PartTimeMusician("John","Doe"); The call to dojo.require("custom.javaworld.Worker") loads the module from the appropriate URI. If it can’t find the .js file for the module, it throws an exception. Package dependency We’ve moved all four classes into one .js file, but it’s always a good idea to create a separate module and separate namespace for each of the modules. Let’s change our sample code so that Worker, ITWorker, Musician, and PartTimeMusician are loaded into different modules: Create ITWorker.js, Musician.js, and PartTimeMusician.js files under the WebContent/js/custom/javaworld folder. Move each class definition within its own .js file. A problem is that the ITworker class has a dependency on the Worker class, and PartTimeITworker has a dependency on ITWorker and Musician. A module can import code that it depends on using a dojo.require() call. The definition of PartTimeMusician should look like this: dojo.provide("custom.javaworld.PartTimeMusician"); dojo.require("custom.javaworld.ITWorker"); dojo.require("custom.javaworld.Musician"); dojo.declare("custom.javaworld.PartTimeMusician",[custom.javaworld.ITWorker,custom.javaworld.Musician],{ As you can see, the PartTimeMusician class is declaring that it has dependency on the ITWorker class and the Musician class by making two dojo.require() calls. Similarly, ITWorker will declare its dependency on Worker by making a dojo.require() call. Once your PartTimeMusician class is ready, you can use it in the index.html file: dojo.require("custom.javaworld.PartTimeMusician"); var johnDoe = new custom.javaworld.PartTimeMusician("John","Doe"); As you can see, we are making only one dojo.require() call to include the PartTimeMusican class. Dojo will take care of loading the dependencies of the PartTimeMusican class and will make sure that each resource is loaded only once. Deploy the latest version of the sample Web application in Apache Tomcat and try accessing it in a browser. If you look into the Firebug console, you will notice that Dojo has loaded Worker.js, Musician.js, and ITWorker.js in addition to PartTimeMusician.js. Using external directories In the sample code so far, we’ve created the custom folder under same root as that of rest of the Dojo code. The problem with this approach is that it can muck up the Dojo root directory. If you keep your development separate from Dojo itself, source control is easier to deal with. Follow these steps to use an external directory instead: Move the custom directory from under WebContent/js to the WebContent directory. Change index.html to register the custom folder name: dojo.registerModulePath("mycode","../../custom"); dojo.require("mycode.javaworld.PartTimeMusician"); The registerModulePath() function is used to map the directory name to the module name. We want to register a module name of custom , which is equal to the /WebContent/custom directory. The second argument of registerModulePath should be the path of the custom directory relative to the Dojo directory. If your custom code is divided into multiple directories, you can make multiple calls to registerModulePath(). You can also use modulePath‘s djConfig variable to map a module name to a directory name. Conclusion to Part 1 Unlike other JavaScript frameworks, Dojo doesn’t focus on only one specific part of JavaScript programming. Instead it is more of a one-stop solution for most JavaScript-related infrastructure. In the second half of this article, you’ll explore some of Dojo’s more advanced features, such as its simplified XMLHttpRequest, which allows you to query and manipulate your document’s DOM structure. You’ll also learn about Dojo’s event model, which enables you to attach event handlers to DOM events. Sunil Patil is a Java Enterprise/Portlet developer working for Ascendant Technology in San Francisco, California. He is the author of Java Portlets 101 (SourceBeat, April 2007) and has written numerous articles published by O’Reilly Media, IBM developerworks, and JavaWorld. Sunil was a member of IBM’s WebSphere Portal Server development team for three years and is actively involved in the Pluto community. In addition to being an IBM Certified WebSphere Portal Server Application Developer for both v5.0 and v5.1, he is a Sun Microsystems Certified Java Programmer, a Web component developer, and a business component developer. You can read Sunil’s blog at http://wpcertification.blogspot.com. Open SourceSoftware DevelopmentWeb DevelopmentApp TestingJavaJavaScriptDevelopment Approaches