The information here was used when designing and building Dijit. It may be out of date.
The Dojo Widget system has shown tremendous success, to the point that to many users "Dojo" is synonymous with the dojo widget system. In particular, it's been successful because of the widget template system and the parser, which allow developers to rapidly develop new widgets, and allow users to rapidly add widgets to their applications. It's also successful because of the many widgets in our library, including simple widgets like ComboButton to more complex widgets that even approach applications, like the Show (aka Powerpoint) widget.
There have been a some downsides to this development though:
In order to tame the beast that is widgets, the widgets have been split off into a project of their own. The main emphasis on the release will be speed, code footprint, and quality. In order to achieve this, only a subset of the existing widgets will be supported (more on this later). And also, only a subset of the existing infrastructure will be supported. Many seldom used features will be dropped.
This page lists general info about how to use dijit. The info for individual widgets is on separate pages.
We're dropping support Konqueror because it doesn't have a big enough install base to warrant our time supporting (coding and testing) it, nor do we want to increase code size/complexity in order to support it.
Opera won't be supported either, at least not for the 0.9 release.
For Release 1.0 all core widgets will:
Internationalization support mainly refers to boilerplate text in widgets, such as error messages like "value out of range". It also refers to date formatting / parsing, which is different in different countries.
All widgets will be documented both API doc and manual.
http:// and https:// (should run without security warnings). file:// doesn't need to work.
See styling section for details.
What does the user have to do to use dojo in their pages?
One of the goals of the redesign is "less magic". Expose more things to the user, such as CSS settings, so that they can control them better. With that principle in mind, some things have changed about how you use dojo in a page:
In the head section, you need to include the CSS for dijit:
<link rel=stylesheet href="dijit/dijit.css" type="text/css">
(but see also the section below on themes)
Next you include dojo (which is now just core dojo stuff, nothing about widgets), and the widgets you are using. In addition, if you want dojo to automatically search the page for widget declarations then you need to include the parser. However, if you are creating your widgets programatically, you don't need to.
<script type="text/javascript" src="dojo/dojo.js"></script>
<script language="JavaScript" type="text/javascript">
dojo.registerModulePath("dijit", "../dijit"); // not needed if dijit and dojo are sibling directories
dojo.require("dijit.form.Button");
dojo.require("dijit.form.Checkbox");
dojo.require("dijit.util.parser"); // scan page for widgets and instantiate them
</script>
Note that widget auto-loading has been desupported. You have to dojo.require() the resources defining the widgets you want to use. (In the above example, dojo.require("dijit.form.Button") defines 3 widgets, the plain-button, drop-down-button, and the combo-button)
Like before, you can create widgets by markup, or programatically.
If you want to create your widget by markup, then you need to include a parser, as documented above. It's this line:
dojo.require("dijit.util.parser"); // scan page for widgets and instantiate them
Then in your body you define widgets in a similar way to the old markup:
<button dojoType= "dijit.form.Button">
Note that unlike Dojo 0.4, the dojoType specifies the full path to the widget prototype. It's case sensitive, and namespaces (like "dojo:Button") are no longer supported. Parameters are specified as in Dojo 0.4:
<button dojoType="dijit.form.Button" type="submit" name="fred" onClick= "foo" disabled>
Note, however, that there can be additional parsers that parse different markup. One suggestion from 3D2 was to encode the widget name and attributes inside the class and style attributes. Another parser might support XML syntax for declarations like <acme:Button disabled= "true">. But XML tends not to work very well inside of browsers, especially IE.
Create widgets via
var myWidget = new dijit.form.Button(params, srcNodeRef)
The createWidget() call has been removed since multiple renderers are no longer supported (see next section).
* Unlike Dojo 0.4, programatic creation will not necessarily create the DOM node for you. You have to create the dom node first, and for a simple widget like a button that doesn't have a template, the DOM node you create must match the logical type of the widget (in this case, a <button> node). In addition, the node has to be part of the document already, or at least it has to have the theme CSS inherited.
Styling of widgets is done completely by CSS. You can use any CSS that you want to style the widgets. You just define rules like
.dojoButton { ... }
There's a small dijit.css file to define essential CSS stuff, but there's no default styling CSS included into a page automatically, so the user has to define something. The user can either write their own CSS, or more typically, include and use one of the predefined "themes":
Dijit comes prepacked with a theme called "tundra". It's called a theme since it's a common look and feel for all widgets, but it's just a bunch of CSS and images:
themes/ tundra/ tundra.css <-- all the CSS for all the widgets checkbox.gif <--- all the checkbox and radio button images fader.gif <--- background image referenced by tundra.cssA preview of tundra lives here
The foreground images are located in the theme directory (along with background images) and are referenced from the widget via CSS rules (via the background-image property of a dummy node).
The tundra.css file has rules like:
.tundra .dojoButton { ... }
You don't have to use the tundra theme, but most people probably will. To use tundra theme for all widgets on your page, do:
<link rel=stylesheet href="dijit/themes/tundra/tundra.css" type="text/css">
(right after including dijit.js)
And then add a theme name to the <body> element, like:
<body class=tundra>
The reason the tundra theme requires a class=tundra on the body tag (or some other tag) is because the rules all list a hierarchy like ".tundra .dojoButton".
Dijit will eventually have multiple themes in the theme directory. You will be able to include additional CSS files into your document, like:
<link rel=stylesheet href="dijit/themes/gloss/gloss.css" type="text/css">
gloss.css will define rules like:
.gloss .dojoButton { ... }
so it won't conflict with tundra.css.
To have different sections of your document that are different themes, you just change the class of each section. For
example, to make the main document tundra theme, but then have sections that are blackGloss and whiteGloss theme, do:
<body class=tundra> ... <div dojoType=dijit.layout.TabContainer> <div dojoType=dijit.layout.ContentPane label=Tab1 class=blackGloss> <input dojoType=dijit.form.TextBox> <button dojoType=dijit.form.Button> ... </div> <div dojoType=dijit.layout.ContentPane label=Tab2 class=whiteGloss> <input dojoType=dijit.form.TextBox> <button dojoType=dijit.form.Button> ... </div> </div> ... </body>
All the widgets in the first tab will have the blackGloss theme and all the widgets in the second tab will have the whiteGloss theme.
You can also define a variation on a theme (much like Handel). Let's say that you like the tundra theme but for each tab above, just want to change the background color of the form widgets. You would define yellowForm and blueForm to just change the background color:
<style>
.yellowForm .dojoButton, .yellowForm .dojoInputField { background-color: yellow; }
.blueForm .dojoButton, .blueForm .dojoInputField { background-color: blue; }
</style>
Then you would reference the override class in a similar way to above:
<div dojoType=dijit.layout.TabContainer> <div dojoType=dijit.layout.ContentPane label=Tab1 class=yellowForm> <input dojoType=dijit.form.TextBox> <button dojoType=dijit.form.Button> ... </div> <div dojoType=dijit.layout.ContentPane label=Tab2 class=blueForm> <input dojoType=dijit.form.TextBox> <button dojoType=dijit.form.Button> ... </div> </div>
The two tabs would then be tundra theme except for the background color on form fields
If you want to develop your own theme, like blackGloss and whiteGloss above, just make rules like
.myTheme .dojoButton { ... }
and include them into your page somehow.
Note that a widget like Checkbox displays the checkbox image using an <img> tag. However, it grabs the image location from the CSS.
The class names used on widgets will never change based on the theme, although they will change based on the state of the widget. for example, an input field will have class="dojoInputField", but a disabled input field will have class= "dojoInputField dojoInputFieldDisabled"
Users apply styles to plain dom nodes in various ways:
<div style= "margin: 30px;">...
<style>
#xyz { margin: 30px; }
</style>
<div id= "xyz">
<style>
.myClass { margin: 30px; }
</style>
<div class= myClass>
The first two techniques should work for widgets also. However, the third technique is not likely to work, because the style rules like ".tundra .dojoButton" will take precendence.
For the ones who want to get the real insight into the CSS depths of the dijit widgeting system, following pages are a good place to start. These docs are work in progress.
All the form widgets support the standard form element attributes such as disabled, tabIndex, id, name, value, in addition to enable()/disable(), and getValue()/setValue(). Of course, changing any parameter value must be done via a method call rather than by just changing the variable value.
All form widgets can be added to a webpage inside a <form> tag, and their value is submitted when the form is submitted. Form reset doesn't work (at least for 0.9).
Some form widgets have the idea of the displayed value (in localized format), and the submitted value (in a standard format). For example, a DateTextBox in America will display 5/30/2007, but you create the widget like this:
<input dojoType=dijit.DateTextBox value=2007-5-30>and also when you submit the form it will send 2007-5-30.
Activating the button via a mouse click or pressing enter or space with focus on the button opens a menu below the button with focus on the first menu item. Pressing up or down arrow with focus on a menu item will cycle focus around through the menu items. Press escape to close the menu and have focus return to the Dropdown button. Pressing tab will close the menu and set focus back to the button.
Mouseover on a menuitem sets focus to that menuitem. Setting focus is necessary so that a screen reader or screen magnifier will work correctly. Mouseout of the menu closes the menu and set focus back to the button.
The current Dojo Tundra theme includes only button text. For those developers using an image for the button face information, a real img element should be used with appropriate alternative text. This will insure that a button with an image is still usable in high contrast mode and with the display of images turned off in the browser.
A combo button is a button with two behaviors - to activate a default action or to open a drop down menu. The drop down menu functionality is implemented as an arrow or other visual indicator within the button face. Activating the main portion of the button executes the default action. Activating the second portion of the button opens a drop down menu of actions.
There are two tab stops within the combo button. One tab stop for the default button action and another for the portion of the button which opens the drop down menu. This implementation is more intuitive for the screen reader user as there is no explicit role to indicate a combination button. The optionsTitle parameter is used to label this button so the screen reader use will know the purpose of the button.
Clicking in the default portion of the button will activate the default action. With focus on the default action portion of the button, pressing the space or enter key will activate the default action. The second portion of the button behaves the same as a Dropdown button.
The default portion of the button has the ARIA role of button. The dropdown button portion of the combo button has the ARIA role of button and the haspopup=true property.
The current Dojo Tundra theme includes only button text. For those developers using an image for the button face information, a real img element should be used with appropriate alternative text. This will insure that a button with an image is still usable in high contrast mode and with the display of images turned off in the browser.
A toggle button is the base class for Checkbox and Radio, and has methods like setSelected(boolean)
Like a textbox but it suggests values for you to type in. No key/value dichotomy. Interfaces to server via dojo.data interface. Can also hardcode data into the HTML file via <select> <option> <option> ...</select> format.
Combobox subclasses the Validation textbox so that it can display error messages if user types a wrong value
See test files (test_Combobox.html, test_FilteringSelect.html) for examples with inlined data or JSON data
If user types in an invalid value, and tabs away, we'll just leave the text they typed in the <input> box. We won't erase the value, nor revert to the last good value, not ignore user keystrokes that cause the text to become invalid (ie, if the user types "californib" or "acalifornia", all the characters will go into the input box).
While this doesn't match the behavior of a browser's <select> or OS drop down, my judgement is that it's the best option, since we don't lose any data the user typed in. It also works well with the asynchronous nature of dojo.data, which prevents us from immediately determining if a given string is valid or invalid.
(bug #3268)
The down button will show all the available choices, so that mouse only users can still use something like a state select box. This is already the current behavior; no change needed.
There will be a widget parameter to show/hide the drop down button. (bug #3269)
This option is means that if you type a partial word (like "cal") and then tab away, it will fill in "California" from the drop down list. It automatically completes your entry.
It doesn't refer to the display of the drop down list. The drop down list always appears; there's no option to turn it off. (The purpose of both these widgets is to have a drop down list.)
(bug #3268)
The drop down list auto-sizes according to the space available; it adds a scrollbar when necessary.
Since our drop downs auto-size to the space available, let's make the drop down always go below the <input> box, unless the space below the input box is really cramped (say, less that 100px).
(bug #3272)
TODO: option to limit the # of items displayed? <a href="">Google suggests</a> only prints 10 items at a time.Validation error message will print tooltip to the right of the box (bug #3267)
At some point we will make a select widget similar to the browser's or OS's select boxes, but not 0.9. See bug #3270 for details.
The browsers focus is put into the text field and the user starts typing. When a match/matches is found, a list of choices is displayed below the textfield that match the information typed into the textfied. As the user continues typing, the list of choices is updated to match what the user has typed.
If the user arrows down into the list of choices a choice is highlighted/selected, the entry in the textfield is updated to match the selected choice and the automatically completed characters are highlighted. As the user arrows through the choices, the textfield is updated, with the automatically completed characters highlighted. The screen reader will speak each choice.
Pressing the down arrow does not change what is displayed in the drop down list.
Pressing the escape key closes the list of choices and returns the text field to the value that the user had typed before selecting from the list of choices. Likewise, pressing the up arrow to move from the list of choices back to the text field returns the textfield value to the value that the user had typed before selecting from the list of choices. The textfield has focus and the caret is at the end of the entry ready for additional input. If the user has a choice selected and types an additional letter, the list of choices is closed and the auto-completed characters are replaced by the newly entered character. Thus, in order to continue typing a different address after having selected one from the list, the user just continues typing. If the user presses enter with a choice selected, the browser closes the list of choices and navigates to the selected choice.
(never written... see test files)
Slider docs: http://www.dojotoolkit.org/developer/dijit/spec/slider
Goal: Port slider from trunk/0.4 to the new dijit structure. Fixing bugs along the way.
Slider is 2 different 'displays'. Vertical and Horizontal.
becka11y asks: the old version of the slider had a flip attribute to change the slider behavior? Will this still be supported? I vote for no since I think it is confusing but if flip is supported the keyboard behavior will have to flip as well to support.
How to deal with Tick Marks, and Labels? Do we allow just tick marks, do we allow them to specify, or draw their own, or do we just do it ourselves however we see fit? Do we allow percentages and discrete numbers?
the spinner widget will deal with adjustments as well(increment/decrement some value.. should we play well with them?)
I've looked at QT and GTK, neither seem to have a good way to deal with the tick marks and labels. I'm going to play with an implementation and see what I come up with.
The slider needs to work in high contrast mode. Any CSS background images or colors are turned off in high contrast mode. Generally to support high contrast we need to use real images to represent at least the slider. This image should have alternative text (probably a + or X to represent the slider when images are turned off. An alternative to an image slider is to use an img button - the button text could have the actual slider value.
At least one of elements in the slider needs to have tabindex="0" so it is in the tab order. This element should receive the ARIA role of slider. The role can probably be set in the slider template. This element also needs the ARIA property values valuemin, valuemax, and valuenow. Valuemin and valuemax correspond to the slider min and max values, respectively. If min and max can be programmitically updated the valuemin and valuemax properties must be updated as well. The valuenow is the current silder value and must be updated via the dijit.util.wai.setAttr() api each time the slider value is updated via the mouse, keyboard or programmatically.
* http://trac.dojotoolkit.org/query?status=new&status=assigned&status=reop... * http://trac.dojotoolkit.org/browser/trunk/src/widget/Slider.js * http://www.flickr.com/photo_zoom.gne?id=343727062&size=o * http://archive.dojotoolkit.org/nightly/tests/widget/test_Slider.html
textarea that automatically changes size based on the content (like the Editor)
This is a standard textbox with various facilities for auto-correcting the input text (capitalization, etc), and hinting w/example values to type in.
TODO: hinting wasn't implemented for 0.9. Need it for 1.0
A Textbox that can take different regular expressions for validating many different patterns. Pops up an error message (like a tooltip) if there is an error.
Displayed value will be localized; user inputs localized value. But the value sent to the server is standard format like javascript numbers.
See currency checkbox comments above.
Like DropdownDatePicker but vastly simpler; no parameters to widget (other than those in FormWidget.js (value, name, id, etc). No advance by week buttons. A stand alone calendar isn't supported. Allows manual input of date by typing. Includes validation if user types wrong date. Combination of Validating textbox and drop down.
These are the widgets that take over when layout out panes via CSS or tables doesn't get you far enough.
nothing written...
This is a stripped down version of the original Content Pane code.
Still can load from href but remove support for CSS and script mangling.
Positions panes at left/right/top/bottom/center.
Horizontal or vertical set of panes where you can adjust the relative size of each pane.
Holds a set of panes only one of which is shown at a time.
Typical tab widgets, holding panes and showing one at a time.
These widgets don't fall into a category so they are in the dijit.* namespace.
(nothing written)
Looks like ModalFloatingPane. You can move the dialog box and close it with an [X]. The dialog box sizes automatically to the content, unless you specify a width and/or max-height.
Nee Editor2. Editor needs to have auto-size mode but also be able to set a fixed size via style attribute or via resizeTo() function, so that editor can be placed in a layout pane.
The context menu from dojo.widget.Menu2. Menu bar not supported.
The progress bar is made accessible by providing a solid border around the visual progress indicator. This border is implemented in an additional z-indexed layer tso it does not change the visual characteristics of the bar when not in high contrast mode.. The layer with the border will be visible in high contrast mode as well as when images are turned off.
The internalProgress div is assigned the ARIA role of progressbar The valuenow attribute is updated as the progress is updated. No valuemin and valuemax values are provided since the valuenow attribute may be a string provided tby the Web developer.
Note: The hot key for the Window-Eyes screen reader to speak progress bar information is ctrl-ins-b. JAWS provides the hot key ins-tab for announcing progress bar name and status.JAWS also has a setting to select the frequency of progress bar announcements. Go to the Configuration Manager, Select Set Options, then User Options and select the desired announcement frequency.
The grid widget provides a scrollable table with sortable columns connected to a dojo.data Store object. It downloads data as needed from the data store, which typically pulls the data from the server in a JSON format. It leverages the store's functionality for sorting, filtering and paging. The table's outer size can be set, so that it fits into a swing-like application with a predetermined size for each section.
Some of the decisions below are based on various email conversations including this thread.
Since the rows have varying sizes, scrolling is complicated. But it should work this way:
The scrollbar's position is relative to the current row #, vs. the total # of rows. If you are on row 75 out of 100 rows, the scrollbar button will be 3/4 of the way down.
The scrollbar button's size can be anything.
The scrollbar must have up/down arrows.
Implementation-wise, this means that we can't have a browser-native scrollbar isn't attached directly to the div holding the data. Probably should have a browser-native scrollbar connected to a dummy div that is hidden behind the div showing the data. Could also use a slider or other custom control for the scrollbar. If we do make a fake scrollbar, then you should use Typematic.js hooked up to the buttons (it's already hooked up for keyboard handling, see the A11Y section below).
var store1 = new dojox.data.RemoteJsonData({documentUrl: "customers.php"});
new dijit.Grid(
{
data: store1,
filter: "date > 2007-1-1",
columns:
[
{ attribute: "name", label: "Name", size: 30},
{ attribute: "dateAdded", label: "Date Added", size: 20 }, ...
]
}, srcNode);
<table dojoType="dijit.Grid" data="store1" style="height: 500px; width: 300px;"> <thead> <tr> <th attribute="Name" dataType="String">Name</th> <th field="DateAdded" dataType="Date" align="center">Date Added</th> <th field="NumAccounts" dataType="Number" sort="desc" align="center"># of accounts</th> <th field="Description" dataType="html">Description</th> </tr> </thead> </table>
The user will call:
var store1 = new dojo.data.JsonItemStore({url: "customers.php"});
or something similar to create the store, and then pass that argument when creating the grid widget.
The Grid is designed to be able to access remote data (hence the paging interface to dojo.data), but the data doesn't necessarily need to be remote. In other words, the Grid accesses it's data via the dojo.data interface and doesn't care where it is. For small datasets, sometimes people will want to embed the data locally in a web page so that there's no server dependency, and for performance reasons.
This can be done with JsonItemStore. The interface looks like this:
var itemData = {items: [{name: "Bill", hiredate: new Date("2006-8-1")}, ...]};
var store = new dojo.data.JsonItemStore({ data: itemData});
For each column we specify the following:
Given a item with the following values:
productCode: 1234
image: shoes.jpg
description: Louis Vitton bag
We might want to write
<icon> 1234 Louis Vitton bagYou can specify the column contents as a function on the item:
expression: function(store, item){
return "<img src=" + store.getValue(item, "image") + "> "
+ store.getValue(item, "productCode") ...
}
This isn't really part of the grid spec, but it's listed here for convenience.
Grid will define functions like:
function onBegin(size){
gets the # of rows in the table.
setup the scrollbar etc. here.
}
function onItem(item){
callback when each row is returned.
for(var i=0; i < this.columns.length; i++){
var value = store.getValue(item, this.columns[i].attribute);
...
}
And then it will do something like this to get the first set of rows:
var params = { query: myQuery, sort: mySort, onBegin: onBegin, onItem: onItem, start: 0, count: 1000};
store.fetch(params);
Then to get next set of rows:
params.start += 1000; store.fetch(params);
And on destruction, or when before redoing the query with a new filter or new sort:
store.close(params);
Note that it's the store's job to do caching, sorting, and querying. The Grid widget doesn't have code for any of that.
For editing an existing row:
store.setValue(item, attr, newValue); ... store.save();
For adding a new row:
var item = store.newItem({attr1: value1, attr2: value2, ...});
store.save();
For deleting a row:
store.deleteItem(item); store.save();
Note: how do I get back to the 300th row, which is not #300 when you sort by date, but maybe row #100 or row #400??? It won't be supported in dojo 1.0 but maybe later
A container with a title bar. The visibility of the container is toggled by activating an arrow "button" on the title bar via the mouse or keyboard.
(proposed).
The arrow to open/close each title pane will be included in the tab order via tabindex="0". The arrow will be given a role of button with a title attribute which indicates that it opens/closes the pane. Pressing enter or space will trigger the button to toggle the open/close of the pane.
When the pane is made visible via the keyboard, the focus remains in the title pane. The user can press down arrow to set focus to the container of the title pane contents (containerNode). Thus, the container Node needs a tabindex="-1" so it can receive focus. When the container is opened, the tabindex should be set to 0 so the user can tab or arrow to the container. When the title pane is closed, the tabindex needs to be set back to 0 (it could also be removed and added as the container is opened or closed but I think it is preferable to just change the tabindex value).
The title pane container will have a labelledby property which points to the id of the titlebar (thus the title bar must have an id attribute). The containerNode will have an ARIA role of region (under discussion since region is not yet supported by screen readers).
(nothing written)
The tooltip pops up like a voice-bubble in comics. It fades in when you mouse over or focus on an element, after a brief delay, and fades out when you mouse away or blur (for keyboard).
Since the tooltip fades out when you mouse off, it's not suitable for holding button or links; use TooltipDialog for that.
The tooltip dialog is like a voice-bubble in comics. It fades in when you click (or hit return on) an element,
and fades out when you close the dialog by hitting cancel, hit escape, or click somewhere else on the screen. It will look similar to odeo's login bubble
Nothing written.