Dojo
Last edited October 20, 2009
More by vanholy »
Sections:
Docs

DOJO Classes

Classes in Dojo are declared with a declare statement with a class name, super-class information, and body. Within the body can be variables and methods. dojo.declare("ClassName", null, {/*class body*/});

dojo.
declare("Person", null, {
        constructor: function(name, age, currentResidence){
                this.name=name;
                this.age=age;
                this.currentResidence=currentResidence;
        },
        moveToNewState: function(newState){
                this.currentResidence=newState;
        }
});


The function named "constructor" is special. It gets called when you create an object with the "new" operator of JavaScript.

//create an instance of a new person
var matt= new Person('Matt', 25, 'New Mexico');

Arrays and Objects as Member Variables

If your class contains arrays or other objects, they should be declared in the constructor so that each instance gets it's own copy. Simple types (literal strings and numbers) and are fine to declare in the class directly.

dojo.declare("my.classes.bar", my.classes.foo, {
        someData: [1, 2, 3, 4], // doesn't do what I want: ends up being static
        numItem : 5, // one per bar
        strItem : "string", // one per bar

         constructor: function() {
                this.someData = [ ]; // better, each bar has it's own array
                this.expensiveResource = new expensiveResource(); // one per bar
        }
});

On the other hand, if you want an object or array to be static (shared between all instances of my.classes.bar), then you should do something like this:

dojo.declare("my.classes.bar", my.classes.foo, {
        constructor: function() {
                dojo.debug("this is bar object # " + this.statics.counter++);
        },

        statics: { counter: 0, somethingElse: "hello" }
});

"Statics" is not a special dojo construct - you can use any name you want, like "constants". In this example, you'd refer to the variable as myInstance.statics.counter both inside and outside the class definition.

Why is this true for arrays and objects, but not primitives? It's because, like most OOP languages, JavaScript uses object references. For example, given:

x = { fruit: "apple" };
y = x;

Now x and y both refer to the same object. Modifying x.fruit will also affect y.fruit.


Inheritance

A person can only do so much, so let's create an Employee class that extends the Person class.The second argument in the dojo.declare() function is for extending classes.

dojo.declare("Employee", Person, {
        constructor: function(name, age, currentResidence, position){
                // remember, Person constructor is called automatically
                this.password="";
                this.position=position;
        },

        login: function(){
            if(this.password){
                alert('you have successfully logged in');
            }else{
                alert('please ask the administrator for your password');
            }
        }
});

Dojo handles all of the requirements for setting up the inheritance chain, including calling the superclass constructor automatically. Methods or variables can be overridden by setting the name to the same as it is in the parent class. The Employee class can override the Person class moveToNewState(), perhaps by letting the company pay for moving expenses.

You initialize the subclass the same as the Person class with the new keyword.

var kathryn=new Employee(' Kathryn ', 26, 'Minnesota', 'Designer');

The Employee class passes the first three arguments down to the Person class, and sets the position.Kathryn has access to the login() function found in the Employee class, and also the moveToNewState() function by calling kathryn.moveToNewState("Texas"); Matt on the other hand, does not have access to the Employee login() function.

matt.login() // ERROR can't log in because he is not an Employee

Calling Superclass Methods

Often when you're overriding a method, you want to add something to the superclasses method, not totally replace it. Dojo has helper functions to make this easy.

But you don't have to worry in the constructor. As we said above, superclass constructors are always called automatically, and always before the subclass constructor. This convention reduces boilerplate in 90% of cases.

For all other methods, you can use inherited(arguments) to call the superclass method of the same name. Take for example:

someMethod: function() {
      // call base class someMethod
      this.inherited(arguments);
      // now do something else
    }

The argument is always literally arguments, a special Javascript array variable which holds all the arguments (like argv in C).

There are a few variations to inherited() for special cases. If you have a method that was put into your object outside of declare, you need to specify the name of the calling function like this:

this.inherited("someMethod", arguments);

And you can send custom parameters to the ancestor function. Just place the extra arguments in array literal notation with brackets:

this.inherited(arguments, [ customArg1, customArg2 ])


Multiple inheritance - Mixins

Suppose, for example, you have a class called VanillaSoftServe, and classes MandMs and CookieDough. Here's how to make a Blizzard:

dojo.declare("VanillaSoftServe",null, {
    constructor: function() { console.debug ("mixing"); }
});

dojo.declare("MandMs",null, {
    constructor: function() { console.debug("never called"); },
    kind: "plain"
});

dojo.declare("CookieDough",null, {
    chunkSize: "medium"
});

dojo.declare("Blizzard", [VanillaSoftServe, MandMs, CookieDough], {
        constructor: function() {
             console.debug("A blizzard with "+
                 this.kind+" M and Ms and "+
                 this.chunkSize+" chunks of cookie dough."
             );
        }
});

Then the following:

new Blizzard();

Will first print "mixing" on the debug console because VanillaSoftServe is the superclass of Blizzard. In fact, VanillaSoftServe is the only superclass of Blizzard - the first mixin is always the superclass. Then "A blizzard with plain M and Ms and medium chunks of cookie dough." will appear.

Mixins are used a lot in defining Dijit classes, with most classes extending Dijit._Widget and mixing in Dijit._Templated.







DOJO Programming 1 - infrastruttura necessaria a creare/"simulare" l'object orientation in javascript
DOJO Parser

This machinery layers on top of dojo.query() to provide a way to declare instances of any class via markup in your page. The parser is:
  • locating the nodes with dojoType attributes in the page
  • taking the attributes assigned to them and passing them into the constructor as properties on the configuration object
  • passing the source node for the widget as the second parameter to the constructor

<script type="text/javascript" src="http://o.aolcdn.com/dojo/0.9.0/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
</script>
<script type="text/javascript">
        dojo.require("dojo.data.JsonItemStore");
        dojo.require("dijit.Tree");
        dojo.require("dojo.parser");

        var countries = new dojo.data.JsonItemStore({ url: "countries.json" });
</script>
</head>
<body class="tundra">
        <div dojoType="dijit.Tree" store="countries" labelAttr="name" typeAttr="type"
           query="{type:'continent'}" >
</div>

In this case, we see the familiar use of the dojoType attribute to denote where an instance of our widget should be created. This is the functional equivalent of writing:

<script type="text/javascript" src="http://o.aolcdn.com/dojo/0.9.0/dojo/dojo.xd.js"
       djConfig="parseOnLoad: true">
</script>
<script type="text/javascript">
        dojo.require("dojo.data.JsonItemStore");
        dojo.require("dijit.Tree");
        dojo.require("dojo.parser");

    dojo.addOnLoad(
        var countries = new dojo.data.JsonItemStore({ url: "countries.json" });
        var tree = new dijit.Tree({
            store: countries,
            labelAttr: "name",
            typeAttr: "type",
            query: {type: "continent"}
        }, dojo.byId("treePlaceHolder"));
    });
</script>
</head>
<body class="tundra">
        <div id="treePlaceHolder"></div>

They're identical. The only difference is that in the first example, the work of locating and creating the widget instance is handed off to the Dojo parser.

To fully understand the parser, it's important to understand it's operation in broad terms. The parser operates by:

  • Searching the document for elements with a dojoType attribute. This search is linear and nodes are returned in document order.
  • Iterating over all matching nodes, attempting to match the declared type with an available class to instantiate.
    • If a class is found, the parser iterates over attributes of the class's prototype and populates the arguments object from the values of attributes on the source node of the same name. Lightweight type conversion is performed.
    • If a markup factory is found for the class, it is used to create a new instance to return
    • If no markup factory is found, the class is constructed using the new operator. The arguments to the constructor are assumed to be in the form new someClass(argumentsObj, sourceNode);
  • Events from markup are attached (although some may have been handled earlier)
Here's a more sophisticated example. We create a class called "example.Class". The parser runs and creates an instance of this class (the div dojoType="example.Class"), which you can then access through the global variable "thinger."
<script type="text/javascript" src="http://o.aolcdn.com/dojo/0.9.0/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
</script>
<script type="text/javascript">
        dojo.require("dojo.parser");

        dojo.declare("example.Class", null, {
                constructor: function(args, node){
                        //  this class constructor is designed for the
                        // parser's "args, node" convention
                        dojo.mixin(this, args);
                },
        });
</script>
</head>
<body class="tundra">
        <div dojoType="example.Class" foo="bar" jsId="thinger">
                <script type="dojo/method">
                        // this block is executed as the class is created but
                        // after the class constructor is finished
                        console.debug(this.foo);   // Prints "bar"
                </script>
        </div>

Each script of type "dojo/method" is executed after the constructor runs. We saw examples of this in Part 1, Example 2.. Finally, the class constructor uses a mixin to copy the attributes from tag to properties in the instance. Thus thinger is created by calling the constructor with args = {foo: "bar"} and node as the div node itself. Foo is created as a property by mixin.

Type Conversions

Lightweight type conversions are done on the attribute values. The types are based on the property types used in the definition of the class. For example:

<script type="text/javascript" src="http://o.aolcdn.com/dojo/0.9.0/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
</script>
<script type="text/javascript">
        dojo.require("dojo.parser");

        dojo.declare("example.Class", null, {
                constructor: function(args, node){
                        //  this class constructor is designed for the
                        // parser's "args, node" convention
                        dojo.mixin(this, args);
                },
                title: "Hello",
                isEnabled: true,
                dayCount: 45,
                onClick: function(){},
                names: ["Monday", "Tuesday", "Wednesday"],
                startDate: new Date()
        });
</script>
</head>
<body class="tundra">
        <div dojoType="example.Class" title="Good Morning" isEnabled="false" dayCount="4" onClick="alert(thinger.dayCount)" names="Thursday, Friday" startDate="2008-01-01" jsId="thinger">
                <script type="dojo/method">
                        // this block is executed as the class is created but
                        // after the class constructor is finished
                        console.debug(this.foo);   // Prints "bar"
                </script>
        </div>

In this example, the attributes will be converted to their correponding types that were used in the definition of example.Class:

  • title: String
  • isEnabled: Boolean
  • dayCount: Number
  • onClick: Function. Specify the function body in the attribute.
  • names: Array. Separate the array members by commas. Array members are assumed to be strings.
  • startDate: Date. "now" can be used to get the current date, otherwise, dojo.date.stamp.fromISOString() will be used to convert the text string to a Date object.

If the property type does not match one of the types listed above, then dojo.fromJson() will be used to convert the attribute value.


Markup Factory

If the class declares a method with the name markupFactory, that function will be used to create the object instance, instead of the constructor. This is useful if the class has special initialization for instances created via markup, versus instances created in script via the class constructor. An example class that defines a markupFactory method:

<script type="text/javascript" src="http://o.aolcdn.com/dojo/0.9.0/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
</script>
<script type="text/javascript">
        dojo.require("dojo.parser");

        dojo.declare("example.Class", null, {
                constructor: function(args, node){
                        //  this class constructor is designed for the
                        // parser's "args, node" convention
                        dojo.mixin(this, args);
                },
                title: "Hello",
                isEnabled: true,
                dayCount: 45,
                onClick: function(){},
                names: ["Monday", "Tuesday", "Wednesday"],
                startDate: new Date(),
                markupFactory: function(params, domNode, constructorFunction){
                        //params: object that contains the markup attribute values,
                        //with type conversion already completed.

                        //domNode: the DOM node (the div in the code below)

                        //constructorFunction: The constructor function matching
                        //the dojoType in markup. In this example, example.Class

                        var instance = new constructorFunction(params, domNode);

                        //Do special initialization intialization here

                        return instance;
                }
        });
</script>
</head>
<body class="tundra">
        <div dojoType="example.Class" title="Good Morning" isEnabled="false" dayCount="4" onClick="alert(thinger.dayCount)" names="Thursday, Friday" startDate="2008-01-01" jsId="thinger">
                <script type="dojo/method">
                        // this block is executed as the class is created but
                        // after the class constructor is finished
                        console.debug(this.foo);   // Prints "bar"
                </script>
        </div>


 DOJO Programming 2 - the Parser
DOJO Creating a Widget Programmatically

In Part 2: Dijit, you saw how to instantiate (create an instance of) a dojo widget declaratively, using the "dojoType" attribute:

<div dojoType="dijit.TitlePane" title="Outer Pane">
   This is a title pane containing another title pane
   <div dojoType="dijit.TitlePane" title="Inner Pane">
      And this is the inner title pane...
   </div>
</div>

While this method is very convenient, widgets declared in this way are instantiated only when the page first loads. What if, however, you want to create a widget at some later time, e.g. as the result of a user-action? This is one case where we would want to instantiate a widget programmatically, which looks like:

var button1 = new dijit.form.Button(params, srcNodeRef);

Let's pick that programmatic example apart:

var button1
This is the name of the variable that will refer to the instantiated widget. You can use this variable to interact with the widget later (see Interacting With Widgets)
dijit.form.Button
This is the fully-qualified name of the widget you want to instantiate; freeing you to, perhaps, later instantiate yourmodule.form.Button (see Writing Your Own Widget Class)
params
An object whose properties map to the widget's properties. Dijit uses this object to initializes the widget's properties. Thus, if the "params" object in this case has a "label" property, dijit will set the dijit.form.Button's "label" attribute to the value of that property. See Setting Properties below for elaboration.
srcNodeRef
This is either a reference to an existing DOM node, or the id of an existing DOM node. When the widget is successfully instantiated, this node will be replaced with the widget's node. New in 1.0: You can skip this parameter for dijit.Tooltip, dijit.TooltipDialog and dijit.Dialog. Since they require no specific place on the page, there's no sense in providing one.

Thus, the programmatic equivalent of:

<div dojoType="dijit.TitlePane" title="Inner Pane">
  And this is the inner title pane...
</div>
from the example above would be:
var innerPane = new dijit.TitlePane( {title:"Inner Pane"}, dojo.byId("someDiv"));
When that line executes, the div with the id "someDiv" will be replaced with a TitlePane widget, with title "Inner Pane".

Programmatically creating widgets allows extra freedom in the parameters. The following is perfectly legal:

var innerPane2 =
    new dijit.TitlePane({
        title: 'Creating New '+docType,
        duration: 5 * 1000    /* 5 seconds, converted to ms */
    }, dojo.byId("someDiv"));

In declarative widgets, you may only pass strings. In programmatic ones, you can pass arrays, nested objects, Dates or Numbers as parameters. This isn't important for bundled Dijit components - they all work with strings - but it can make building your own widgets easier.
New in 1.0: When programmatically creating a widget class, style, and id now need to be specified as parameters to the constructor, not as attributes of the placeholder node. For example, the following is incorrect:

<script>
// Doesn't work in 1.0.  Class and style will be overwritten
new dijit.form.Button({},,dojo.byId("someDiv"));
</script>

<div id="someDiv" class="large" style="color:red"></div>

The correct code:

// Works in 1.0
new dijit.form.Button({ "class": "large", style: "color: red" }, dojo.byId("someDiv"));

startup()

Certain widgets require a startup() method to be called. When building widgets programmatically, you create the parent first, then add the children, and grandchildren... and finally call startup(). Startup() is called once on the top element in the hierarchy, after the whole hierarchy has been setup and the element inserted.

It's good practice to include the startup() call, even for widgets that have no children or do not require it.

accordion = new dijit.layout.AccordionContainer({}, dojo.byId("accordionShell"));
accordion.addChild(new dijit.layout.ContentPane());
accordion.addChild(new dijit.layout.ContentPane());
accordion.addChild(new dijit.layout.ContentPane());
accordion.startup();

Interacting With Widgets


Retaining a Widget Reference
If the widget was created programmatically, you can simply retain a reference to what you created:
var widgetReference = new dijit.form.Button(params, srcNodeRef);
Obtaining a Widget Reference
If the widget was created declaratively, or you didn't retain a reference to a programmatically-created widget, you can obtain a reference to the widget object if you know its widgetId. You do this using dijit.byId("idOfWidget")

<div dojoType="dijit.form.Button" label="Click" id="button1"></div>
dojo.addOnLoad(function() {
            var widgetReference = dijit.byId("button1");
            widgetReference.setLabel("Don't Click!");
          });
Note: This is different than a DOM id. In the above example, dijit.byId("button1") returns a reference to the widget, and dojo.byId("button1") returns a reference to the actual DOM node of the button.

Using the Reference

  • The DOM Node

    You can access the (root) DOM node of the widget via the "domNode" property of the reference.

  • Common Dijit-Widget Interactions

    Popups
    Popups can be opened/closed using open() and close()
    StackContainer widgets
    StackContainer widgets such as TabContainer and AccordionContainer use a transition() method to switch between two widgets (for example, you might do chained animation, fading out one widget before wiping in the second).
  • Animations

    You can make an arbitrary animation to show/hide a widget using the dojo.fx code (slideIn, fadeIn, or something more complicated using animateProperty and/or combined animations on myWidget.domNode

  • Events















 DOJO Programming 3 - Creating a Widget Programmatically
DOJO Events

Dojo.connect has the following signature (acceptable types in square brackets):

handle = dojo.connect(Scope of Event [object or null], Event [string], Context of Linked Method [string or null], Linked Method [string or function], Don't Fix Flag [boolean])

All of the options for calling dojo.event are explored further below.

Example Code for Reference

<head>
<title>Dojo Events are Great</title>
<script src="dojo/dojo.js" type="text/javascript"></script>
<script type="text/javascript">

function foo() { console.debug("A click upon your houses!"); }

function globalGuy() { console.debug("Global Guy fired!"); }

var someObject = {
   bar: function() { console.debug("Bar fired!"); return 7; },
   baz: function() { console.debug("Baz fired!"); return 14; }
}

var anotherObject = {
    afterBaz: function () { console.debug("afterBaz fired!"); }
}
</script>
<body>
<a id="firstLink" href="http://dojotoolkit.org/">Dojo</a> is an excellent tool kit.
</body>

Connecting to a DOM Event

To connect a function to a DOM event with Dojo, you first need to get the node that you want to connect to. Here, I'll use the venerable dojo.byId.

To summarize how things have been since dojo 0.1/0.2 time....
-- use dojo.byId if you would have normally used document.getElementById()
-- use dijit.byId if you need the access any functions/properties of a widget
-- dom events are lowercase, all dojo/dijit events/functions are camelCased (ie: 'onClick' == dijit onClick stub 'onclick' == dom node onclick stub

firstLinkNode = dojo.byId("firstLink");

Now, to fire foo when a user clicks #firstLink, and I have the node, so I just need to use dojo.connect for the heavy lifting.

firstLinkConnections = [];
firstLinkConnections[0] = dojo.connect(firstLinkNode, 'onclick', foo)

In this example, I passed dojo.connect the object I want my function to listen to (in this case, a DOM node), the name of the function that should trigger my function's call (in this case, the "onclick" event), and the name of my function. Note that I keep a reference to the connection by setting firstLinkConnections[0] to the return value of dojo.connect. This will allow me to disconnect the listener later, if I desire. Now, when a user clicks "Dojo," a message appears in the log Because my function is global in scope, I can pass it directly to connect. The following, however, are equivalent:

firstLinkConnections[0] = dojo.connect(firstLinkNode, 'onclick', null, foo);

and

firstLinkConnections[0] = dojo.connect(firstLinkNode, 'onclick', null, "foo");

Now, if I also want to connect someObject.bar() to #firstLink, I can do that.

firstLinkConnections[1] = dojo.connect(firstLinkNode, 'onclick', someObject, "bar");

Because I've used Dojo's event handling, I can connect an arbitrary number of functions to fire on an event.

A note about the event names: In most cases, event names now are lower case, except in special cases (e.g., some Mozilla DOM events). Dojo will add "on" to your event name if you leave it off (e.g., 'click' and 'onclick' are the same thing to dojo). Dojo responds to all of the usual events (e.g., onclick, onmouseover, etc.) and the onkeypress event for capturing typing.

A note about return values: Any value returned by a function called by dojo.connect will be lost.

Connecting Functions to One Another

Connecting functions to one another is even simpler than connecting them to DOM events; because you already have a reference to the function, you don't need to do any byId or query work. To have anotherObject.afterBaz fire after someObject.baz fires, use the following:

objectConnections = [];
objectConnections[0] = dojo.connect(someObject, "baz", anotherObject, "afterBaz");

In the above code, the first argument is the context of "baz," the second argument is the event (in this case, when baz fires), the third argument is the context of your listener function, and the fourth argument is the listener function itself. Connecting two global functions is even easier:

objectConnections[1] = dojo.connect(foo, globalGuy);

Now, whenever foo is called, globalGuy will also fire. As you might expect, connecting a method to a global function, or vice versa, is logical and simple:

objectConnections[2] = dojo.connect(foo, anotherObject, "afterBaz");
objectConnections[3] = dojo.connect(someObject, "baz", globalGuy);

Disconnecting

To disconnect listeners from events, you simply pass the connection handle (the return value of dojo.connect to dojo.disconnect. To disconnect globalGuy from someObject.baz, I use the following code:

dojo.disconnect(objectConnections[3]);


Event Object

Submitted by MattBowen on Tue, 06/05/2007 - 18:33.

When you connect a function to a DOM event with dojo.connect, dojo passes your function a normalized event object. This means that, regardless of the client's browser, you can count on a set of standard attributes about the event and a set of methods to manipulate the event.

Syntax

Assume that your function has been called by dojo.connect and takes an argument named event

Dojo provides the following attributes with an event object:

  • event.target — the element that generated the event
  • event.currentTarget — the current target
  • event.layerX — the x coordinate, relative to the event.currentTarget
  • event.layerY — the y coordinate, relative to the event.currentTarget
  • event.pageX — the x coordinate, relative to the view port
  • event.pageY — the y coordinate, relative to the view port
  • event.relatedTarget — For onmouseover and onmouseout, the object that the mouse pointer is moving to or out of
  • event.charCode — For keypress events, the character code of the key pressed

Dojo provides the following methods with an event object:

  • event.preventDefault — prevent an event's default behavior (e.g., a link from loading a new page)
  • event.stopPropagation — prevent an event from triggering a parent node's event

Additionally, dojo.stopEvent(event) will prevent both default behavior any any propagation (bubbling) of an event.

Example Code for Reference

<head>
<title>Dojo Events are Great</title>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"></script>
<script type="text/javascript">

function echo(event) {
        key = event.charCode;
        console.debug(event.charCode);
}

function foo(event) {
        dojo.stopEvent(event);
        console.debug("The link was clicked");
}
dojo.addOnLoad(function() {
        interactiveNode = dojo.byId("interactive");
        linkNode = dojo.byId("link");
        dojo.connect(interactiveNode, 'onkeypress', echo);
        dojo.connect(linkNode, 'onclick', foo);
});
</script>
<body>
        <a href="http://dojotoolkit.org" id="link">Dojo</a> is great.
        <form>
                <label for="infield"> Type some text: </label>
                <input id="interactive" type="text" name="infield">
        </form>
</body>

Using a Dojo Event Object

In the example code, we have two functions that are connected to two different events. Echo sends the key code of any key typed in the text input field to the console. It does so by using the charCode property of the normalized event object. Foo is connected to the #link and cause it to send "The link was clicked" to the console instead of changing the browser's location; by using the preventDefault method of the normalized event object, connections to change the default behavior of DOM objects.

Now, imagine that you want to detect for the down arrow key in the text box. To do this, we just need to attach a new event listener to the text box and check to see if each keycode is the keycode for the down arrow. And how do you know what the keycode for the down arrow is, you may ask? Well, Dojo provides constants for every non-alpha-numeric key [[link to sub page to come]]. In our case, we are interested in dojo.keys.DOWN_ARROW. So, assuming that you want to just log when the down arrow is pressed, the following code should do the job:

dojo.connect(interactiveNode, 'onkeypress', function (evt) {
        key = evt.keyCode;
        if(key == dojo.keys.DOWN_ARROW) {
                console.debug("The user pressed the down arrow!");
        }
});



dojo.addOnLoad starts your scripts after the DOM has loaded but before all of the page elements have loaded.

Acting in parallel to dojo.addOnLoad is dojo.addOnUnload , which runs functions when the page is being "unloaded" (e.g., when the user clicks a link off of the current page). This gives you the opportunity to send notifications to your web application or clean up unavoidable memory leaks.



  DOJO Programming 4 - Events - Call a Function
DOJO AJAX

Many programming tutorials contain a "Hello, World!" example, so it seems appropriate to have one for Dojo XHR. In this example, your web page will fetch a snippet of content via XHR and attach it directly to your page.

To setup the example:

  1. Create a file named ajax.txt. It's your decision what to put in the file. "Hello, Ajax world!" is a good start.

  2. Put ajax.txt in the default documents directory on your web server. In many cases, that is the httpdocs directory.

  3. Open your web browser and navigate to the file. You should see the contents of ajax.txt.

  4. Create a file named hello.html. Copy and paste the contents of Example 1, “Hello, Ajax world!” into that file.

  5. Set the URL argument to the value you used to test the server setup.

  6. Put hello.html in the default documents directory on your web server. In many cases, this is the httpdocs directory.

    Put the file in the same directory as ajax.txt.

  7. Make the file read-only.

  8. Open your web browser and navigate to hello.html. You should see the contents of ajax.txt in your browser window.

Example 1. Hello, Ajax world!

<html>
<head>
<title>Hello, Ajax world!</title>
<script type="text/javascript"
src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"></script> <!---->
<script type="text/javascript">
function hello() { //
dojo.xhrGet( { //
// The following URL must match that used to test the server.
url: "http://server/ajax.txt",
handleAs: "text",

timeout: 5000, // Time in milliseconds

// The LOAD function will be called on a successful response.
load: function(response, ioArgs) { //
dojo.byId("cargo").innerHTML = response; //
return response; //
},

// The ERROR function will be called in an error case.
error: function(response, ioArgs) { //
console.error("HTTP status code: ", ioArgs.xhr.status); //
return response; //
}
});
}
</script>
<script type="text/javascript">
dojo.addOnLoad(hello); //
</script>
</head>
<body>
<div id="cargo" style="font-size: big"></div> <!---->
</body>
</html>

This JavaScript program bootstraps Dojo 1.0 via the AOL Content Distribution Network. If you choose to install Dojo locally, use the following script tag to bootstrap Dojo:

<script type="text/javascript" src="dojo/dojo.js"></script>

Modify the directory reference in the SRC attribute to match the location of your Dojo installation

This function will be called after Dojo completes its initialization phase.
The desired HTTP method call (GET, POST, PUT, DELETE) is part of the function name.
Inside this function, the this variable will be the object used as the argument to the dojo.xhrGet() call.
This statement demonstrates one way of stuffing a server response into a document. The dojo.xhrGet call asks Dojo to treat data from the server as text (handleAs: "text"). Therefore response will be a text string.

Dojo recommends that you always return(response); to propagate the response to other callback handlers. Otherwise, the error callbacks may be called in the success case.

ioArgs is an object with some useful properties on it. For instance, for XMLHttpRequest calls, ioArgs.xhr is the XMLHttpRequest that was used for the call.

The Dojo team recommends that you always use dojo.addOnLoad() to call any startup code you write. Even for this simple example, unless we use dojo.addOnLoad(), we cannot reliably assume that the main function hello() will run after Dojo initialization completes.

Use dojo.addOnLoad() only to run start-up code. Do not use dojo.addOnLoad() to call JavaScript event handlers.

Two ways to abuse Dojo. The following techniques will produce tedious, head-scratching debugging sessions by not using dojo.addOnLoad().

<body onload='hello'>
This technique is never a good idea when using Dojo. You have no assurance that hello() will run after Dojo initialization.
Put the hello() body in a <script> without dojo.addOnLoad()
This technique usually fails with Dojo. Only the simplest JavaScript programs, like "Hello, Ajax world!" can employ this technique. It's a safe bet that yours isn't one of them.
Holding area for the server response. A common use case is that the server returns an HTML fragment that the client will want to display. The innerHTML attribute of such placeholder <div> tags is a convenient way to display HTML fragments.
 

Passing Data with JSON

Submitted by dante on Mon, 04/30/2007 - 23:39.

JSON, or Javascript Object Notation, is a lightweight data interchange standard.   It can, in theory, be used to pass data between any two programming languages, but it has special advantages when used with Javascript.  JSON is fundementally just the Javascript array and object initializer syntax on its own.  So this array of objects in a Javascript program:

var cobblers = [
   {"filling": "peach", "timeToBake": 30 },
   {"filling": "cherry", "timeToBake": 35 },
   {"filling": "blueberry", "timeToBake": 30}
];

Roughly everything after the "=" is JSON.  Here's what the JSON packet would look like coming back from a web service:

{ "cobblers": [
       {"filling": "peach", "timeToBake": 30 },
       {"filling": "cherry", "timeToBake": 35 },
       {"filling": "blueberry", "timeToBake": 30}
    ]
}

"Excuse me," you might say, "but we already have a data interchange format.  You might have heard of it ... it's called XML."   So why not just pass it as:

<cobblers>
   <cobbler filling="peach" timeToBake="30" />
</cobblers>

The answer is performance, performance, performance!  JSON data is parsed up to 100 times faster than XML.  That makes sense because the parser is just eval().  For small portions of data, this doesn't mean much, but for large ones it's indispensible.  XML expressed in Javascript must carry the full weight of XML - including namespaces, DTD's and schemas.  Furthermore, the DOM representation of XML is much more memory-intensive than native Javascript.

Add to that the fact that XML is interpreted a little differently in each browser, and JSON is the preferred method for data interchange in dojo.  XML is supported, but you might not want to use it in simple scenarios. Where it really begins to make sense, however, is when large scale transformations are needed on the client side. Almost every modern browser today provides a client-side XSLT transform facility which can often outstrip JSON for speed in transforming large data sets from one structure to another since that transformation is handled in C or C++ and not in JavaScript. Whether your app chooses to use JSON or XML is often a foregone conclusion, but be aware that there are tradeoffs for each.

Accepting JSON Data in dojo.xhrGet

Provided your web service sends JSON (as the above example shows) Dojo pretty much handles the rest for you, including parsing the JSON into a JavaScript object. All you have to do is specify a JSON content handler:

dojo.xhrGet( {
        // The following URL must match that used to test the server.
        url: "http://server/ajax.txt",
        handleAs: "json",

        load: function(responseObject, ioArgs) {
          // Now you can just use the object
          console.dir(responseObject)// Dump it to the console
          console.dir(responseObject.cobblers[0].filling)// Prints "peach"
          return responseObject;
        }
        // More properties for xhrGet...
});

Errors and Timeouts

Submitted by jchimene on Tue, 06/05/2007 - 18:44.

Regular web requests and Ajax requests with dojo.xhrGet/Post are much alike. Both use URL's and both use the HTTP protocol. But with browser requests, it is always clear to user when something goes wrong. You may get a 404 - Page Not Found, or a Server Unavailable, or at least something that says "Error". Ajax requests happen in the background, so when they error out the user won't know. Even worse, if the response never comes the browser may appear to lock up.

That's why it's extremely important to provide an error handler and a timeout handler with any dojo.xhrGet/Post calls. You should consider these as critical as URL or the load function

At the very least, you should alert the user that something went wrong. Here's an example:

dojo.xhrGet({
        url: "/cgi-bin/timeout.cgi",
        load: function(data){
                document.myForm.myBox.value = data;
                dojo.byId("boxLoadTime").innerHTML = new Date();
        },
        error: function(err){
                console.debug("Holy Bomb Box, Batman!  An error occurred: ", err);
        },
        timeout: 2000
});

The error() function takes the same arguments that load() does. But unlike load(), the only useful parameter is data, which contains the error message. You can also find out what kind of error was generated by looking at the error object's "dojoType" property. It will usually be "timeout" or "cancel", but other error types are possible.

The timeout, given in milliseconds, defaults to 0, which means "wait forever". Even if you expect the request will take a long time, you should set a high value here (e.g. 15000 = 15 seconds), not 0.


 DOJO AJAX Tutorial - Cenni su Json
DOJO LOG

Method 1: Logging

The first method is logging, and if you've used modern logging tools like log4j you'll find it familiar. The idea is to write trace messages to a log which you can then use to find variable values or the last executed bit of code.

Why not just use alert() ? The trusty JavaScript alert() is a favorite debugging tool, but it suffers from the following problems:

  • If you have many alerts, it's annoying to keep clicking [OK]
  • Too much text can make the dialog box overflow the screen
  • You must remember to remove every alert() before release
  • alert() in a tight loop might make it impossible to stop without killing the browser process
  • You cannot easily print object contents or arrays

Clearly alert's just not powerful enough. In Dojo logging, you can associate messages with severity, just like in log4j. The following code illustrates the five severity levels:

console.log("Nothing happening");
console.debug("Checking to make sure nothing happened");
console.info("Something might happen.");
console.warn("Something happened, but it's no big deal.");
console.error("Cough cough!");

In the Firebug console, the messages will appear like this:

In IE, they will appear like this:

Another useful method, console.dir() dumps variable contents to the screen. While console.log works fine for strings and integers, console.dir prints more complex variables - objects, arrays, arrays of objects, or whatever. For example:

console.dir([
   {attribute: "last_name", sortDescending: true},
   {attribute: "last_name", sortDescending: true}
]);

produces:

So in our example above, we write:

console.debug("dojo.newWidth is" + dojo.newWidth);
this.domNode.style.width = dojo.newWidth;

Running this, we quickly find that dojo.newWidth is undefined. Maybe we spelled it wrong? To quickly find out, we change the debugging statement to:

console.dir("dojo is" + dojo);
this.domNode.style.width = dojo.newWidth;

Nope, there's no property in dojo that looks like newWidth. Finally, we spot our error and change the right hand side to "newWidth." Case closed.

Method 2: The "debugger" Statement

Alternatively you can set a "poor person's breakpoint" in the code. Just insert the debugger; statement, which is a legal JavaScript reserved word.

debugger;
this.domNode.style.width = dojo.newWidth;

This statement stops the code and brings you to a Firebug command prompt. It appears the code has stopped at ... huh?


That's a side effect of running dojo/event code. The breakpoints don't seem correct at all.

But just click the Console tab and now you can examine variables or execute just about any JavaScript you want. In this case, we look at the dojo.newWidth property, which has nothing in it. But "dojo" does and we examine it by console.dir(dojo). Basically all the logging features of method 1 are available to type here.

To Follow The dojo.require Trail, Use Dojo Locally

Since that code is now running, we try a minor variant which sets the button to blue:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Fix me!</title>
    <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
            djConfig="parseOnLoad: true">
</script>
    <script type="text/javascript">
        dojo.require("dojo.parser");
        dojo.require("dijit.form.Button");
    </script>
</head>
<body class="tundra">
<div dojoType="dijit.form.Button">
   Click to break!
   <script type="dojo/event" event="onClick">
      this.domNode.style.backgroundColor = dojo.Color.named.aliceblue;
   </script>
</div>
</html>

You check the console ... no errors there. But that dojo.Color.named.aliceblue is a little questionable. You know that dojo.colors needs to be included, but you thought dijit.form.Button already did that.

You can find out for sure by using a local copy of Dojo. CDN Dojo is very quiet about the modules it loads. Local Dojo is very noisy. So, assuming our local copy of Dojo is installed on the web server underneath /dojoroot, the following change:

<style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
            djConfig="parseOnLoad: true">
</script>

Yields the following on the console

You see every Dojo Core and Dijit Component loaded. Sure enough, dojo.colors is not in the list, so we add a dojo.require statement

That Doesn't Look Right ... DOM Inspection

Unfortunately, that doesn't fix the problem either. When styling errors occur, it's a good time to use Firebug's DOM Inspector. You can think of it as View Source on steroids.

  • It displays the current DOM tree, not the one initially loaded (which is what View Source shows)
  • You can examine the DOM properties of nodes by inspecting them - that is, pressing Inspect and pointing

So we click Inspect and point at the screen button

The right-hand side of the console tells what styles and style rules are applied to this class. Crossed-off lines are styles that have been overriden. Very nice!

Debugging External Classes With debugAtAllCosts

dojo/method and dojo/event scripts are good for short, non-reusable snippets of code. But when you start building reusable components, you'll be storing your code into Dojo-declared classes instead. The good news is the more you make this switch, the easier your debugging task will be.

So here's a piece of HTML code and a reusable Dojo-based widget:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Goolica Tax Form</title>
    <style type="text/css">
        @import "/dojoroot/dijit/themes/tundra/tundra.css";
        @import "/dojoroot/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="/dojoroot/dojo/dojo.js"
            djConfig="parseOnLoad: true">
</script>
    <script type="text/javascript">
        dojo.require("dojo.parser");
        dojo.require("dojobook.online-book.debugging.BuggyWidget");
    </script>
</head>
<body class="tundra">
    <div dojoType="dojobook.online-book.debugging.BuggyWidget"></div>
</body>
</html>
dojo.provide("dojobook.online-book.debugging.BuggyWidget");

dojo.require("dijit._Widget");

dojo.declare(
"dojobook.online-book.debugging.BuggyWidget",
[dijit._Widget],
{
   postCreate: function() {
      dojo.nonExistentMethod();
   }
});

Running this code, you will see an error appear, but it's nowhere near the right location:

But by simply setting the debugAtAllCosts flag to true:

<script type="text/javascript" src="/dojoroot/dojo/dojo.js"
            djConfig="parseOnLoad: true, debugAtAllCosts: true">
</script>

the displayed error location will now be correct:

Important! you should always remove debugAtAllCosts from production code. It slows down the client unnecessarily. Rather than manually inserting and removing them, I like to delegate that job to a server side language like PHP:

<?php
$djConfig     = $inProduction ? "parseOnLoad: true" : "parseOnLoad: true, debugAtAllCosts: true";
$loadLocation = $inProduction ? "http://o.aolcdn.com/dojo/1.0.0" : "/dojoroot";
$useXd        = $inProduction ? ".xd" : "";
?>

    <style type="text/css">
        @import "<?= $loadLocation ?>/dijit/themes/tundra/tundra.css";
        @import "<?= $loadLocation ?>/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="<?= $loadLocation ?>/dojo/dojo<?= $useXd ?>.js"
            djConfig="<?= $djConfig ?>"></script>




 DOJO sistema di log simile log4j
DOJO Callback

In Java you can define classes anonymously, on-the-fly, right in the middle of a method call.  You can do that in Javascript too.  Simply define the function in the parameter list and omit the name.  For example, instead of defining and passing a new function:

function myTwoParameterFn(a, b) {
   return max(a, -b);
}
console.debug(myTwoParameterFn(1, 2, Math.max));

We can shorten it to:

console.debug(myTwoParameterFn(
    1, 2,
    function(a,b){
        return max(a, -b)
    }
));

This makes from some pretty strange syntax, especially if the anonymous function is large.  But callbacks are often specified this way when calling dojo functions. 

 
 in Dojo le callback sono strutturate come funzioni innestate in altre funzioni
Snippet

<!--A HEAD snippet which loads the style sheet and Dojo libraries, then calls functions to load individual dijit types.-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<head>
<title>Events</title>
 
<script type="text/javascript" src="dojoroot/dojo/dojo.js"></script>
<script type="text/javascript">
function echo(event) {
        key = event.charCode;//object Event
        console.debug(event.charCode);//object event
}

function foo(event) {
        dojo.stopEvent(event);
        console.debug("The link was clicked");
}
dojo.addOnLoad(function() {
        interactiveNode = dojo.byId("interactive");
        linkNode = dojo.byId("link");
        dojo.connect(interactiveNode, 'onkeypress', echo);
        dojo.connect(linkNode, 'onclick', foo);
});
</script>
<body>
        <a href="http://dojotoolkit.org" id="link">Dojo</a> is great.
        <form>
                <label for="infield"> Type some text: </label>
                <input id="interactive" type="text" name="infield">
        </form>
</body>
</html>
 DOJO Eventi e utilizzo di event object
DOJO - Simple Ajax 

<!--A HEAD snippet which loads the style sheet and Dojo libraries, then calls functions to load individual dijit types.-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<head>
<title>Prova di chiamata a server</title>

<style type="text/css">
        @import "dojoroot/dijit/themes/tundra/tundra.css";
        @import "dojoroot/dojo/resources/dojo.css"
</style>
   
<script type="text/javascript" src="dojoroot/dojo/dojo.js"
         djConfig="parseOnLoad: true">
</script>

<script type="text/javascript">
    dojo.require("dijit.form.Button");
</script>


<!--The two arguments to the functions (data, and ioArgs) are important -->
<!-- don't leave any of them out! The first argument (data) contains the -->
<!-- data sent back from the server, whilst the second argument -->
<!-- contains a Dojo I/O Bind object.-->
<script>
       function helloCallback(data,ioArgs) {
          alert(data);
       }      
       function helloError(data, ioArgs) {
          alert('Error when retrieving data from the server!');
       }
</script>

</head>

<body class="tundra">

<button dojoType="dijit.form.Button" id="servletButton">Hello Servlet!
    <script type="dojo/method" event="onClick">
        dojo.xhrGet({
            url: 'Start',
            load: helloCallback,
            error: helloError           
               });
    </script>
</button>

<!--This property - content - allows the programmer -->
<!--to send arbitary values to the server as parameters.-->
<!--In this case, since we are using the default method -->
<!--of dojo.io.bind which is GET, the server side script -->
<!--will have the value of the textbox available -->
<!--to it as a the GET parameter 'name'-->

<!--va bene anche post basta che cambio la funzione dojo.xhrPost-->
<button dojoType="dijit.form.Button" id="helloJSP">Hello JSP!
    <script type="dojo/method" event="onClick">
        dojo.xhrGet({
            url: 'HelloWorldResponseGET.jsp',
            load: helloCallback,
            error: helloError,
            content: {name: dojo.byId('name').value }
               });
    </script>
</button>
 Please enter your name: <input type="text" id="name">
       
</body>
</html>
 DOJO Esempio Base di una chiamata Ajax
DOJO

<!--A HEAD snippet which loads the style sheet and Dojo libraries, then calls functions to load individual dijit types.-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">

<head>
<title>Taxes, The Surest Thing Next to Death!</title>

<style type="text/css">
        @import "dojoroot/dijit/themes/tundra/tundra.css";
        @import "dojoroot/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="dojoroot/dojo/dojo.js"
            djConfig="parseOnLoad: true"></script>


    <script type="text/javascript">
   
    dojo.require("dijit.form.Button");
    dojo.require("dijit.form.DateTextBox");
    dojo.require("dijit.form.TextBox");
    dojo.require("dijit.form.ComboBox");
        dojo.require("dijit.form.CheckBox");
        dojo.require("dijit.TitlePane");
    dojo.require("dijit.form.CurrencyTextBox");
   
       
</script>


</head>

<!--A class to the BODY tag specifying the name of your theme. In our examples, we'll use the "Tundra" theme.-->
<body class="tundra">
<!--<body class="a11y"> per visione ad alto contrasto-->
<button dojoType="dijit.form.Button" id="helloButton">Hello World!
<!-- metodi Dojo all'interno del bottone,
posso gestire anche eventi come pressione tasti.
I metodi vanno bene per tutti i Browser-->
  <script type="dojo/method" event="onClick">
             alert('You pressed the button');
          </script>
</button>
       
       
<br>

<img src="symbol_help.gif" id="helpIncome"/>
<div dojoType="dijit.Tooltip" style="display:none" connectId="helpIncome">
    Agente <b>Bauer</b>: c'è un emergenza in corso!
</div>


<!--Dijit introduces a new attribute "dojoType". You simply add that to the tag you wish to "dijit-ize".-->
<!--We use the dojoTypes dijit.form.TextBox and dijit.form.Checkbox.-->
<form>

First Name:
<input type="text" size="20" name="first"  dojoType="dijit.form.TextBox"
           trim="true" propercase="true" / > <br>
Last Name:
<input type="text" size="20" name="last"  dojoType="dijit.form.TextBox"
           trim="true" propercase="true"  /> <br>
Email Address:
<input type="text" length="20" name="email"  dojoType="dijit.form.TextBox"
           lowercase="true" /> <br>
Filing Date: <input type="text" length="10" name="filingDate" dojoType="dijit.form.DateTextBox" /><br>

<select name="plop.combo" dojoType="dijit.form.ComboBox">
 <option value="one">one</option>

 <option value="two">two</option>

 <option value="three">three</option>
</select><br>

<hr>
<ol>
<li>Please Enter Your 2007 Gross Income




<!--<input type="text" length="10" name="grossIncome"  dojoType="dijit.form.TextBox"/></li>-->

<input type="text"
                maxlength="12"
                class="fillwidth currency"
                id="grossincome" name="grossincome"
                value="0.00"
                dojoType="dijit.form.CurrencyTextBox"
                required="true"
                onChange="updateTotals()"
                currency="USD"/>


<li>Please enter the value from line 1.  This is your <em>2007 tax</em>
<input type="text" length="10" name="tax"  dojoType="dijit.form.TextBox" /></li>

<li>Would you like to contribute an extra $3 to the Presidential Campaign Fund?
<input type="checkbox" name="campaign" value="Y"  dojoType="dijit.form.CheckBox" /></li>
</ol>
<div dojoType="dijit.TitlePane" open="false"
     title="Directions (click to Expand)" style="width:300px;height:170px">

Proin risus. Nullam rhoncus purus id turpis. Praesent aliquam adipiscing ligula. Aenean lorem ante,
accumsan quis, elementum id, cursus eu, lorem. Fusce viverra. Ut tempor nisi at ipsum. Etiam sed nibh.
</div>
</body>
</html>
 File di esempio con configurazione base e semplici widgets
The content on this page is provided by a Google Notebook user, and Google assumes no responsibility for this content.