Login Register

User Interaction

Pretty nice so far, but this app is long on displaying, short on interaction. So next Andy decides to add some toolbars, tooltips and dialog boxes. "Surely this will involve lots of JavaScript," he thinks.

Here's the cocktail napkin view of the toolbar:

mail_step3a.png

We already have the dijit.Toolbar widget in the app as a placeholder. Dijit.toolbar expects its immediate children to be buttons:

  • dijit.form.Button is a plain ol' command button, but better.
  • dijit.form.DropDownButton, when clicked, displays a menu of commands
  • dijit.form.ComboButton combines the two - acting like a button when clicked, or a menu when held-down.

Getting Mail - ComboButton and Tooltip

The New Mail button is a ComboButton:

<button id="getMail" dojoType="dijit.form.ComboButton"
        iconClass="mailIconGetMail">

        <script type="dojo/method" event="onClick">
                fakeDownload();
        </script>
        <span>Get Mail</span>
        <ul dojoType="dijit.Menu">
                <li dojoType="dijit.MenuItem" iconClass="mailIconGetMail">Yahoo</li>
                <li dojoType="dijit.MenuItem" iconClass="mailIconGetMail">GMail</li>
        </ul>
</button>
<span dojoType="dijit.Tooltip" connectId="getMail">Click to download new mail.</span>

The dijit.Tooltip does what you think it should - it displays a message when the user hovers over the button. It knows this by connecting the connectId to the id attribute of the widget.

At the heart of a ComboButton or DropDownButton is a dijit.Menu, itself composed of dijit.MenuItem objects. Andy chooses not to wire the items - Yahoo and GMail - to an event handler yet. But he does tie the onClick handler of the ComboButton itself.

Like for the Tree, Andy uses a dojo/method script to fire off a snippet of JavaScript. In this case, it's a stubbed out function called fakeDownload(). But wait! Can't you just do this?

<!-- It works, but uses DOM Level 0 event model.  Yuck. -->
<button id="getMail" dojoType="dijit.form.ComboButton"
        iconClass="mailIconGetMail"
        onclick="fakeDownload();">

Yes, but you wouldn't want to. Using dojo/method and connecting to the extension point gets you the DOM Level 2 event model for free. DOM Level 2 events pass much more information to the event handler. And before you ask ... yes, this even works in Internet Explorer, which doesn't natively support the DOM Level 2 event model. Dojo adds a nice layer which emulates the model on IE.

Sweet! That's cross-browser functionality for free. Dojo is really, really good at that.

New Mail and Options - Dialog Boxes

So let's look at the other buttons:

<button
        id="newMsg" dojoType="dijit.form.Button"
        iconClass="mailIconNewMessage">

        New Message
        <script type="dojo/method" event="onClick">
                alert("New message functionality coming soon.");
        </script>
</button>
<span dojoType="dijit.Tooltip" connectId="newMsg">Click to compose new message.</span>
<button id="options" dojoType="dijit.form.Button" iconClass="mailIconOptions">
        Options 
        <script type="dojo/method" event="onClick">
                dijit.byId('optionsDialog').show();
        </script>
</button>
<div dojoType="dijit.Tooltip" connectId="options">Set various options</div>

There's nothing here we haven't seen before ... except the call to optionsDialog. This displays a dialog box, which should look like this:

mail_step3b.png

Now this looks like a regular HTML form, and in fact we'll code it as if it were. But ... we'll use a dijit.Dialog to do it. The good news is that unlike HTML forms, a dijit.Dialog acts modally, leaving all the information and page state alone while the user fills in the dialog details. So the server interaction happens in the background.

The code for the dialog box goes at the bottom of our app, just above the /BODY tag, separated away from all the other HTML:

<div dojoType="dijit.Dialog" id="optionsDialog" title="Options:">
        <table> 
        <tr>
            <td style="text-align:right;"><label for="option1">Transport type:</label></td>
            <td>
                <select id="option1" dojoType="dijit.form.FilteringSelect">
                    <option value="pop3">POP3</option>
                    <option value="imap">IMAP</option>
                </select>
            </td>
        </tr>
        <tr>
            <td style="text-align:right;"><label for="option2">Server:</label></td>
            <td>
                <input id="option2" dojoType="dijit.form.TextBox" type="text">
            </td>
        </tr>
        <tr>
            <td style="text-align:right;">
                <input type="checkbox" id="fooCB" dojoType="dijit.form.CheckBox">
            </td>
            <td><label for="fooCB">Leave messages on Server</label></td>
        </tr>
        <tr>
             <td style="text-align:right;">
                 <input type="checkbox" id="fooCB2" dojoType="dijit.form.CheckBox">
             </td>
             <td><label for="fooCB2">Remember Password</label></td>
        </tr>
        <tr>
            <td colspan="2" style="text-align:center;">
                <button dojoType="dijit.form.Button" type="submit"
                              iconClass="mailIconOk">
OK</button>
                <button dojoType="dijit.form.Button" type="submit"
                              iconClass="mailIconCancel">
Abort</button>
             </td>
        </tr>
        </table>
</div>

You can look at dijit.Dialog as a mini-form, with Dijit form elements sprinkled into it. Note, we don't do anything with the data here, but a finished app would save the settings and communicate them back to the server.

Andy places the dojo.require's in the header

dojo.require("dijit.form.Button"); 
dojo.require("dijit.Menu");
dojo.require("dijit.Tooltip");
dojo.require("dijit.Dialog");
dojo.require("dijit.form.ComboBox"); 
dojo.require("dijit.form.CheckBox"); 
dojo.require("dijit.form.FilteringSelect");
dojo.require("dijit.form.Textarea");

And step 3 is done. "Wow," Andy thought, "that's a lot less JavaScript than I thought." To tell the truth, there is a lot of JavaScript behind it, but you didn't have to write it. Dojo has it all!

AttachmentSize
step3.html5.97 KB

dijit.form.TextBox not Textarea

The dojo.require references dijit.form.Textarea when it is actually dijit.form.TextBox that is used in the dialog form

inconsistent use of enclosing tag for dijit.Tooltip

dijit.Tooltip is enclosed in div tag and span tag. I'm assuming it should be enclosed in a span tag, since div defines a division/section in the document whereas the span tag is used to group inline-elements to format them with styles, which seems to be the case here.

Robert Matousek

The use of the span and div

The use of the span and div are probably just to illustrate that the html element used to define the widget can be just about any html element...since the dojo "parsing" process, at page load time, replaces the html element with whatever is defined in the widget template, typically several html elements, each with a different role.

However, for some semblance of fallback (in case Javascript is disabled), it is sometimes recommended that the sacrificial html element be one that could at least partially fulfill the role intended for the widget.

Example: If you are creating a dijit.form.Button widget, you would use the html button element/tag, a dijit.form.FilteringSelect might indicate using a select tag, etc.