Login Register

Basic tutorial: extending a dijit into a custom namespace

a simple, yet elegant(?) extension on a vanilla dijit widget. hopefully Karl won't yell at me for putting this in dijit support ... it is kind of development-esque ...

[explain idea of dijit being extensible]

So, because there are no official (or even un-official) tutorials aimed at the 0.9 code base, this is my attempt in all of it's glory, to provide just that: A simple example of extending an existing stable widget into my own desired form. I want an AccordionContainer with image headers instead of plain HTML text. Simple enough? let's delve, and begin:

Getting Dojo

you can probably skip this step, but for the brave, lets do this step-by-step:

I have a web location (http://dojotoolkit.org/~dante/) that i can put my files. I need the Dojo Toolkit, and for the sake of 0.9beta vs 0.9production I will use the most recent SVN checkout: (i assume you are using some *nix varient at this point)

dante@foo:~/public_html$ svn co http://svn.dojotoolkit.org/dojo/view/anon/all/trunk dojo
Lots of stuff will fly by. A lot of it you won't need. But this is SVN HEAD. It's the kitchen sink of Dojo. Profiles and builds will assist in limiting your overhead, but for the sake of this tutorial, and for the sake of development, we're going to be using:
[snip] A dojo/util/docscripts/modules/dojox.module A dojo/util/docscripts/README Checked out external at revision 9904. Checked out revision 9904.

There are other releases of Dojo. There was a 0.9beta release, though many many fixes have been made preparing for Dojo 0.9production ready release, which will eventually lead to the Dojo Toolkit 1.0 (and probably a beta beforehand, hehe). SVN insures we have "what is happening" in Dojo _today_. subversion is your friend.

we now have a /home/dante/public_html/dojo/ folder, with four sub-folders: dojo, dijit, dojox, and util ...

myNamespace - a home for custom widgets

Lets assume for the moment we can model our custom code to work in our ~/public_html/dojo/ folder, ignoring dojo.registerModulePath() and all that, and use the convenience provided by Dojo's robust package system.

when you dojo.require("custom.nameSpace.widget") , it checks (relative to dojo.js): ../custom/nameSpace/widget.js and ../custom/nameSpace.js. with this in mind, if we put a folder (for our widgets) as a sibling of our dojo/ dijit/ dojox/ folders, we can _easily_ harness the simplicity of the Dojo package system.

lets make our custom namespace folder:

dante@poquito:~/public_html/dojo$ ls -la
total 32
drwxr-xr-x  7 dante dante 4096 2007-07-31 04:11 .
drwxr-xr-x  8 dante dante 4096 2007-07-31 03:22 ..
drwxr-xr-x 14 dante dante 4096 2007-07-31 03:23 dijit
drwxr-xr-x 14 dante dante 4096 2007-07-31 03:23 dojo
drwxr-xr-x 24 dante dante 4096 2007-07-31 03:26 dojox
-rw-r--r--  1 dante dante  187 2007-07-31 03:22 README
drwxr-xr-x  7 dante dante 4096 2007-07-31 03:29 .svn
drwxr-xr-x  7 dante dante 4096 2007-07-31 03:29 util
dante@foo:~/public_html/dojo$ mkdir dojoc
dante@foo:~/public_html/dojo$ cd dojoc/
dante@foo:~/public_html/dojo/dojoc$ mkdir widget

assume we will be only modifying things in our custom folder from here out ...

It's alllll relative

our little test file is going to live at http://dojotoolkit.org/~dante/accordionTutorial.html, so we open /home/dante/public_html/accordionTutorial.html and put some basic Dojo-essentials in:




	Toaster Widget Dojo Tests
	
	



	

dojoc.widget.ImageAccordion

It's poorly named, I know. An "ImageAccordion" would be an AccordionContainer of "ImagePane"'s (but one does not exist). This is an example of an AccordionContainer, with Images exclusively as their Titles, named "dojoc.widget.ImageAccordion".

it's a pretty standard beginning for any dojo-enabled webpage. our link to dojo.js is dojo/dojo/dojo.js, so the package system will search dojo/ for all require() calls. __package__.js (widget.*) support exists, but the new 0.9 way is "full classname" ... lets add a dojo.require() for our custom widget (anywhere after our dojo.js script tag, and before our body tag):

it we load our page now, we get an error thrown "Could not load dojoc.widget.ImageAccordion, last tried ..." ... We need to make our widget, jerky.

Our first (only?) Widget: An accordion Container, but with image titles.

declare the class:

load up your favorite text editor. We're making ~/public_html/dojo/dojoc/widget/ImageAccordion.js ... this is our code for the custom widget. The relative paths should make sense (dojo.js is ~/public_html/dojo/dojo/dojo.js). Lets get rid of the error, and declare our class: (this is, and will be refered to as ImageAccordion.js from here out :) )

dojo.provide("dojoc.widget.ImageAccordion"); // all packages need to dojo.provide() _something_, and only one thing
dojo.require("dijit.layout.AccordionContainer"); // the module with dijit.layout.AccordionPane
dojo.declare("dojoc.widget.ImageAccordion", // our declared class
	dijit.layout.AccordionPane, // we inherit from, this is a _Templated _Layout widget 
	// class properties: 
	{

	/* none, at the moment. this is sort-of an alias for AccordionPane right now. */

});

see, no more errors. it's not much of a widget though. Lets 'steal' the code from dijit.layout.AccodionContainer, and make our widget useful, and pretty. First, make sure we dojo.require() what we'll need (in the event it's not already loaded), and update our inheritance arg to extend AccordionContainer ... woop. Stop. We're not really extending AccordionContainer, we're extending AccordionPane, the "templated widget" that is a child of an AccordionContainer, so we provide(ImageAccordion), but extend AccordionPane to become ImageAccordion.

our test html

We're going to borrow a test-case from AccordionPane. in dojo/dijit/tests/layout/test_Accordion.html you will find some examples of using an AccordionContainer. Lets copy some text over, put it in our test HTML, rename references to dijit.layout.AccordionPane to dojoc.widget.ImageAccordion (really poorly named, really.), and hope it works as expected ... add a dojo.require("dijit.layout.AccordionContainer") with the rest of your require()'s and replace the with our Accordion test:

Hello World
Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin suscipit porta magna. Duis accumsan nunc in velit. Nam et nibh. Nulla facilisi. Cras venenatis urna et magna. Aenean magna mauris, bibendum sit amet, semper quis, aliquet nec, sapien. Aliquam aliquam odio quis erat. Etiam est nisi, condimentum non, lacinia ac, vehicula laoreet, elit. Sed interdum augue sit amet quam dapibus semper. Nulla facilisi. Pellentesque lobortis erat nec quam. Sed arcu magna, molestie at, fringilla in, sodales eu, elit. Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus ut elit convallis eleifend. Fusce tincidunt, justo quis tempus euismod, magna nulla viverra libero, sit amet lacinia odio diam id risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu, porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac, faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu, consequat quis, varius interdum, nulla. Donec neque tortor, sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean ut eros sit amet ante pharetra interdum.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.

and we should now see a normal AccordionContainer with normal AccordionPanes (three of them) ... Seems to be working.

our Template:

Granted, what we've done so far could be accomplished by just declaring dojoc.widget.ImageAccordion = dijit.layout.AccordionPane. But we're going to be adding some stuff, and modifying the template some, so we're going the dojo.declare() route. If we were just wanting to replace to TemplatePath url with our own custom file we coud simply dijit.layout.AccordionPane.prototype.templatePath = "myCustomTemplate.html" and affect all accordionPanes in this scope, but we're not, and you wouldn't get to learn about custom namespaces. We want two widgets: Accordion (html), and Accordion (image titles).

So we know what we're working with, lets just copy the origional AccordionPane.html template to our custom widget template folder:

dante@foo:~/public_html/dojo/dojoc/widget$ mkdir templates
dante@foo:~/public_html/dojo/dojoc/widget$ cp ../../dijit/layout/templates/AccordionPane.html templates/ImageAccordion.html
and update our ImageAccordion.js to use it, instead:
// in class properties:
templatePath: dojo.moduleUrl("dojoc.widget","templates/ImageAccordion.html")
... save, reload. Works in IE6, FF2, and WebKit at this point. Go us. Lets take a look at our new template, and figure out what needs to be done to change the "Title" to become just a plain image ... rename some CSS class (we can "borrow" some of the formatting ones next), move the title- text variable into an alt="" tag for our titleNode,focusNode img node (leaving the events in tact), and introduce a src="" variable so we can link our images from an attrib ...

${title}

looks pretty good. dojo.parser will complain about the new "${src}" reference if we don't go invent it, so add in your class properties:

// src: String
//	src url for AccordionPaneExtension header
src: ""

and go ahead and add some src="imgage.png" attribs to the AccordionContainer children in your test page. I made 3 simple ones, 200px x 26px. Add in some basic CSS for the classes we changed, and voila:




	dojoc.widget.ImageAccordion Test
	

	
	



	

dojoc.widget.ImageAccordion

It's poorly named, I know. An "ImageAccordion" would be an AccordionContainer of "ImagePane"'s (but one does not exist). This is an example of an AccordionContainer, with Images exclusively as their Titles, named "dojoc.widget.ImageAccordion".
Hello World
Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin suscipit porta magna. Duis accumsan nunc in velit. Nam et nibh. Nulla facilisi. Cras venenatis urna et magna. Aenean magna mauris, bibendum sit amet, semper quis, aliquet nec, sapien. Aliquam aliquam odio quis erat. Etiam est nisi, condimentum non, lacinia ac, vehicula laoreet, elit. Sed interdum augue sit amet quam dapibus semper. Nulla facilisi. Pellentesque lobortis erat nec quam. Sed arcu magna, molestie at, fringilla in, sodales eu, elit. Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus ut elit convallis eleifend. Fusce tincidunt, justo quis tempus euismod, magna nulla viverra libero, sit amet lacinia odio diam id risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu, porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac, faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu, consequat quis, varius interdum, nulla. Donec neque tortor, sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean ut eros sit amet ante pharetra interdum.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
Sed arcu magna, molestie at, fringilla in, sodales eu, elit. Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum consequat quis, varius interdum, nulla. Donec neque tortor, sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean ut eros sit amet ante pharetra interdum.

and our current ImageAccordion.js file:

dojo.provide("dojoc.widget.ImageAccordion"); 
dojo.require("dijit.layout.AccordionContainer");
dojo.declare("dojoc.widget.ImageAccordion", // our declared class
	dijit.layout.AccordionPane, // we inherit from
	// class properties:
	{

	templatePath: dojo.moduleUrl("dojoc.widget","templates/ImageAccordion.html"),

	// src: String
	//	src url for AccordionPaneExtenion header
	src: ""
	
});

We've just made our first Custom widget. Next: Fancy hover states for Title Images!