HTML Widget Prototyping with the Dojo Toolkit November 2nd, 2007 at 10:58 am by Mike Wilcox
The first Dojo Toolkit 1.0 Release Candidate is complete. To celebrate, let’s take a look at one of the new features in Dijit’s dijit.Declaration.
We are already familiar with Dijit’s capabilities to render widgets in markup. This is a powerful way of providing widgets in your page with about the same effort as styling with CSS. Recently, Alex Russell blogged about new Dojo alternate script types as a way of attaching code via markup through a creative use of the script tag’s type attribute. One of the newest features in the Dojo Toolkit, dijit.Declaration, extends that approach by giving us a way to define widgets in markup.
Let’s start with a bare-bones HTML document that includes the Dojo Core, dojo.parser, and Dijit. The new parameter “parseOnLoad=true”, included as part of the djConfig attribute in our initial script tag, tells the dojo.parser to go to work. It’s the standard mechanism used when defining a user interface using the markup versions of Dijit constructors. We then include our resources: dijit.Declaration and the dojo.parser.
<html> <script type="text/javascript" xsrc="dojotoolkit/dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script> <script> dojo.require("dijit.Declaration"); dojo.require("dojo.parser"); </script> <body> </body> </html>
Now, within the body tag, we will create a placeholder for the widgets that we will be defining. This will be the definition of our widget.
<div dojoType="dijit.Declaration" widgetClass="TextField" defaults="{defaultText:''}"> <input type="text" dojoAttachPoint="tNode" value="${defaultText}"/> </div>
We have created our root element, and gave it a dojoType of dijit.Declaration. This tells the dojo.parser that we intend for this to be the declaration of a widget, including the widget’s template. The widgetClass is the name of our widget, and we have set a property default of defaultText to an empty string. Note the defaults object is in quotes.
If we tried to display the page now, it will be blank. That’s because this is a declaration and the parser consumed it, converted into a constructor object, and is now waiting to be instantiated. In other words, we have to create the actual widget based on our template, emulating the new constructor:
<div dojoType="TextField" defaultText="Type Here"></div>
Note that we called our widgetClass, and set the property. Now when we refresh the page, our widget is created:

Our widget is displayed, and as you can see, the parser read in the template and found our placeholder for the defaultText property, and replaced it with the value.
Now that we have our markup widget, let’s give it some methods. Let us say if the user leaves a blank field, we want to insert the default text. We will use the alternate script types that Alex showed us:
<div dojoType="dijit.Declaration" widgetClass="TextField" defaults="{defaultText:''}"> <input type="text" dojoAttachEvent="onchange" dojoAttachPoint="tNode" value="${defaultText}"/> <script type="dojo/method" event="onchange"> var txt = dojo.trim(this.tNode.value); console.log("CNG"); if(txt.length == 0){ this.tNode.value = this.defaultText; } </script> </div>
Using a script-type of dojo/method, the browser skips the script. The dojo.parser then picks it up and converts it to code and inserts it into our widget. Since this is a method type, we’re creating a function, which fires on the onchange event we attached to the input node.
Let’s finish it up. On creation, we will lighten the font color, and when a user clicks on the field, the default text is removed:
<div dojoType="dijit.Declaration" widgetClass="TextField" defaults="{defaultText:''}"> <input type="text" dojoAttachEvent="onchange, onfocus" dojoAttachPoint="tNode" value="${defaultText}"/> <script type="dojo/connect" event="postCreate"> this.tNode.style.color = "#CCCCCC"; </script> <script type="dojo/method" event="onchange"> var txt = dojo.trim(this.tNode.value); console.log("CNG") if(txt.length == 0){ this.tNode.value = this.defaultText; this.tNode.style.color = "#CCCCCC"; } </script> <script type="dojo/method" event="onfocus"> if(this.tNode.value == this.defaultText){ this.tNode.value = ""; this.tNode.style.color = "#000000"; } </script> </div>
Note that to tie into the creation of the widget, we used dojo/connect and, using the Dojo event method “dojo.connect” behind the scenes, connected to the native postCreate method of the widget. Then we created another method, and wired that up to the additional event we attached: onfocus.
Additionally, you could create a base form widget, and extend that with various input and buttons widgets. To extend another markup widget, you would use the mixins method, which might look something like this:
<span dojoType="dijit.Declaration" widgetClass="FormButton" mixins="MarkupForm"> </span>
Validation and user feedback can be written, coded, and styled all on the same page. You can see the possibilities of this technique, not only with form fields but with page layouts and more, all quickly prototyped without the need for an extensive supporting infrastructure.



Posted November 2nd, 2007 at 12:36 pm
Congrats on the 1.0 release. dijit.Declaration definitely looks useful. I’ll have to explore it this weekend.
Posted November 3rd, 2007 at 11:39 am
From a technical standpoint, this looks very cool. However, what I’m not clear on is ‘why’ one would want to do this. Is it not just one more abstraction away from JavaScript? Since this code would have to be placed on every page that it is used, the user will have to download the code again and again, with no caching. For a very small widget this may not be an issue, but for a widget with multiple complex methods, this could become a serious performance problem.
I guess I just don’t see the advantage of this approach, over the standard pattern of declaring a JavaScript widget, having it compressed and gzipped, then cached client side. Once anything complex has to be done, you still have to write quite a lot of JavaScript, only you declare the functions with a tag instead of in JavaScript.
I’m sure I’m missing the point somehow, but if I am, then so are others….
Oh, and congrats to all the Dojo team (and me! :-) ) on the 1.0 release.
Posted November 3rd, 2007 at 1:24 pm
@Shane: You’re observation is definitely reasonable. I’m more of a “reporter” of this technique, so this is strictly my opinion:
It’s obviously not good for large apps for precisely the reasons you state. As I prepared for this blog I considered what they best uses may be. Naturally I blogged on what I thought best - maybe page layouts and other things that need to be tended to once or twice on a page.
I think this is a new idea, and it’s a great thing to throw out there and see what users do with it and perhaps it will lead to something we haven’t thought of.
However, I think the real story is in Alex’s alternate script types. When I first heard about that a while back, I got quite excited, as I think that has a lot of potential. Dijit.Declaration would be just one example.
Posted November 5th, 2007 at 11:20 am
Hi Shane,
The basic idea behind it is less production deployment and more *very* rapid prototyping; instead of having to set up the infrastructure for a custom widget, you can do it all inline in a single page and work it up from there. Once you’re satisfied with the basics of the widget, you can then turn around and do your normal custom widget split up (with your JS, HTML and CSS stuff) based on it.
Posted November 5th, 2007 at 3:49 pm
Hi Tom,
Thanks for the clarification.I can see how this would be a very quick way to prototype something. However, it would be nice if the developer was able to reuse this code once, the prototype phase is completed.
A couple of ideas:
1. Make it possible to extract the dijit.Declaration code out into a file, which can then be pulled in via dojo.require, and instantiated. This would be relatively simple to do - just fetch the text, append it to the tag, and instantiate it as usual.
Much more interesting in my mind is:
2. Add an XSLT transform to the Dojo build system so that widgets/dijits declared in this manner, in their own file with some custom extension (.dijit, whatever) and written out as a .js file, all nicely transformed into a JavaScript object. This would allow developers to decide what paradigm they’d like to write in - pure JS, or an XML based syntax - and stick to that.
Another advantage of the second approach is that users are insulated from changes to the Dijit infrastructure in future releases. If their custom code is encapsulated in tags, with templates and attachPoints defining their HTML layout, then the rest of the code can be defined by the XSLT transform, and the generated code will always conform to the latest API.
Of course, these options are in no way mutually exclusive.
This may seem like a “I hate JavaScript and would like someone else to write it for me” comment, but it’s not. I doubt I would personally use this, but I figure that if you’re going to go this far, and introduce an abstraction, why not go the extra 10% and get all these extra benefits?
Posted January 16th, 2008 at 8:00 pm
The other thing about the Declaration widget is that its great for developing widgets with complex templates, and especially where you need some paramaterization of the template on the server-side. As the element /is/ the template for a Declaration, that template can be generated the same way as you generate the rest of the page, without having to deal with escaping and concatenating html in strings.
I’ve found it most useful for the “last mile” in a widget inheritance chain, where you inherit from something that does pretty much everything you need, and just supply a specialized template and perhaps some constructor code or an onClick method or something - and keep it right inline with the rest of the page/html it belongs with.
Posted February 13th, 2008 at 6:22 am
[…] an official release and we’re talking about new and changed features. In my previous post, I demonstrated Dijit’s brand new ability to construct widgets in markup. Now we’ll return to the more familiar Dijit Widget and see the culmination of the previous […]
Posted February 13th, 2008 at 11:26 am
This code does not appear to work for dojo 1.0.2. Can anyone shed any light on this?
Code as I understand it:
End.
Posted February 13th, 2008 at 11:56 am
I think it would be helpful to have final sample code, not just fragments. This works for a local copy of 1.0.2: