- The Book of Dojo
- Quick Installation
- Hello World
- Debugging Tutorial
- Introduction
- Part 1: Life With Dojo
- Part 2: Dijit
- Part 3: JavaScript With Dojo and Dijit
- Part 4: Testing, Tuning and Debugging
- Part 5: DojoX
- The Dojo Book, 0.4
Direct Extension
Submitted by dante on Sun, 09/16/2007 - 12:18.
Every widget class is a Dojo class. So you should be able to extend a widget class just like you would any other Dojo class, right? Like with dojo.declare? Absolutely!
What do you gain by using dojo.declare instead of dijit.Declaration? Mostly you gain flexibility. For example, say you wanted to declare a widget class with the same functionality, but two completely different versions of a template based on a user preferences. No problem. You construct the template itself with JavaScript code, then pass it to dojo.declare in the template property.
But let's get back to ImageAccordion. Following the examples in Modules, we'll place this class dojoc.layout.ImageAccordion in a file named dojoc/layout/ImageAccordion.js under the Dojo root. Here's how to write it in code:
// all packages need to dojo.provide() _something_, and only one thing
dojo.provide("dojoc.widget.ImageAccordion");
// AccordionContainer is the module with dijit.layout.AccordionPane
dojo.require("dijit.layout.AccordionContainer");
// our declared class
dojo.declare("dojoc.widget.ImageAccordion",
// we inherit from this class, which in turn mixes
// in _Templated and _Layout
[ dijit.layout.AccordionPane ],
// class properties:
{
templatePath: dojo.moduleUrl("dojoc","layout/templates/ImageAccordion.html"),
// Necessary to keep Dijit from using templateString in AccordionPane
templateString: "",
// src: String
// src url for AccordionPaneExtension header
src: ""
});
dojo.provide("dojoc.widget.ImageAccordion");
// AccordionContainer is the module with dijit.layout.AccordionPane
dojo.require("dijit.layout.AccordionContainer");
// our declared class
dojo.declare("dojoc.widget.ImageAccordion",
// we inherit from this class, which in turn mixes
// in _Templated and _Layout
[ dijit.layout.AccordionPane ],
// class properties:
{
templatePath: dojo.moduleUrl("dojoc","layout/templates/ImageAccordion.html"),
// Necessary to keep Dijit from using templateString in AccordionPane
templateString: "",
// src: String
// src url for AccordionPaneExtension header
src: ""
});
The src string does pretty much what we think - unlike with dijit.Declaration, we must declare the new attributes explicitly. The templatePath requires some explanation.
Attaching the Template to a Direct Extension
With dijit.Declaration, the template is just the body of the tag. In dojo.declare land, there are three ways to specify a template:
- Use the templatePath attribute to point to a URL with a template in it.
- -OR- Specify the template directly in the templateString attribute
- -OR- Pass a DOM node with a parsed representation of the template
The first option is preferred because it separates the JavaScript and HTML code cleanly. With templateString, you must remember to escape all the quote marks, required in a JavaScript string. The Custom build system will convert the template in templateUrl to an inline templateString to help performance, so no need to worry there. Note: as in our above example, if you are overriding a widget with a templateString, and you want to use a templateUrl in your subclass, be sure to set templateString to "".
The templates are stored in the module along with all the JavaScript code. We place this template file into dojoc/widgets/template/ImageAccordion.html:
<div class='dojocImageAccordion'
><div dojoAttachPoint='titleNode,focusNode'
dojoAttachEvent='ondijitclick:_onTitleClick,onkeypress:_onTitleKeyPress,onfocus:_handleFocus,onblur:_handleFocus'
class='dojocImageAccordionTitle' wairole="tab"
><img alt="${title}" src="${src}"
></div
><div><div dojoAttachPoint='containerNode'
style='overflow: hidden; height: 1px; display: none'
class='dojocImageAccordionBody' waiRole="tabpanel"
></div></div>
</div>
><div dojoAttachPoint='titleNode,focusNode'
dojoAttachEvent='ondijitclick:_onTitleClick,onkeypress:_onTitleKeyPress,onfocus:_handleFocus,onblur:_handleFocus'
class='dojocImageAccordionTitle' wairole="tab"
><img alt="${title}" src="${src}"
></div
><div><div dojoAttachPoint='containerNode'
style='overflow: hidden; height: 1px; display: none'
class='dojocImageAccordionBody' waiRole="tabpanel"
></div></div>
</div>
- Printer-friendly version
- Login or register to post comments
- Unsubscribe post

Option 3
I don't see any details here on how to achieve Option 3 ('Pass a DOM node with a parsed representation of the template"). Is this related to the src="" attribute?
thx.
Errors in JS and the template
Few problems:
1) In the JavaScript
dojoc.widget.ImageAccordion should be dojoc.layout.ImageAccordion
2) I only see ${title} for dojoc/widgets/template/ImageAccordion.html (using FireFox 2.0.0.13). I had to view the source to determine what the template should be.
3) The template doesn't look right. It uses custom CSS classes.
Here are the artifacts of the example:
1) HTML file - You may need to fix the relative paths. It references an image file that needs to change. My project structure was:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Programmatic Widget Extension</title>
<script type="text/javascript" src="../../dojo/dojo.js"
djConfig="parseOnLoad: true"></script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.Declaration");
dojo.require("dijit.layout.LayoutContainer");
dojo.require("dijit.layout.AccordionContainer");
dojo.registerModulePath("dojoc","../dojoc");
dojo.require("dojoc.layout.ImageAccordion");
</script>
<style type="text/css">
@import "../../dojo/resources/dojo.css";
@import "../../dijit/themes/tundra/tundra.css";
@import "../../dijit/demos/mail/mail.css";
@import "custommail.css";
</style>
</head>
<body class="tundra">
<div dojoType="dijit.layout.LayoutContainer" id="main">
<div dojoType="dijit.layout.AccordionContainer" sizeMin="20" sizeShare="20" layoutAlign="client">
<div dojoType="dojoc.layout.ImageAccordion" title="Folders" src="../postman/folder.gif">
Folders will go here
</div>
<div dojoType="dijit.layout.AccordionPane" title="Address Book">
Addresses go here
</div>
</div>
</div>
</body>
2) Java script file
dojo.provide("dojoc.layout.ImageAccordion");
// AccordionContainer is the module with dijit.layout.AccordionPane
dojo.require("dijit.layout.AccordionContainer");
// our declared class
dojo.declare("dojoc.layout.ImageAccordion",
// we inherit from this class, which in turn mixes
// in _Templated and _Layout
[ dijit.layout.AccordionPane ],
// class properties:
{
templatePath: dojo.moduleUrl("dojoc","layout/templates/ImageAccordion.html"),
// Necessary to keep Dijit from using templateString in AccordionPane
templateString: "",
// src: String
// src url for AccordionPaneExtension header
src: ""
});
3) ImageAccordion.html:
><div dojoAttachPoint='titleNode,focusNode'
dojoAttachEvent = 'ondijitclick:_onTitleClick,onkeypress:_onTitleKeyPress,onfocus:_handleFocus,onblur:_handleFocus'
class='dijitAccordionTitle' wairole="tab"
><div class='dijitAccordionArrow'></div
><img alt="${title}" src="${src}"/> ${title}</div
><div><div dojoAttachPoint='containerNode'
style='overflow: hidden; height: 1px; display: none'
class='dijitAccordionBody' waiRole="tabpanel"
></div></div>
</div>
Hope this will help someone
When extenting another
When extenting another Widget, does one have to be careful of overriding its parents methods i.e. the 'startup' method perhaps or does dojo.declare take care of this?
yes and no
sometimes you _want_ to override a method, so dojo.declare does that. sometimes you want to call your own code of the method before or after, and this.inherited does that:
startup:function(){
/* my code */
this.inherited(arguments); // "arguments" is key
/* and / or more code */
}
});
So, one must explicitly
So, one must explicitly call
this.inherited(arguments);in order to invoke the parent function o the same name. Is this then considered good practice if one doesn't fully understabd the functionality of the parent?
shouldn't the empty templateString
be above the templatePath?