Andy has been studying up on Dojo 1.0, and found one of the great new features - the Dijit grid. A grid is like a mini spreadsheet, or a maxi-HTML-table. You can sort the columns, edit cells, and enable all kinds of cool stuff. It sounds like the perfect container for a message list.
[inline:mail_step7.png]Once you've worked with Dojo awhile, you start to see Grand Unifying Themes. One of them is dojo.data, feeding server-pulled data to different kinds of widgets. Grid is no different. Fortunately, Andy already has the data store defined. And since that data store has messages in it, hierarchically tied to folders, it's a short step to display them. First he adds the separate Grid style sheet:
/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}A grid has two main elements: the model and the structure. The model is the data behind the grid, while the structure is a set of display instructions.
Andy does the model first. We already havy the data in a dojo.data store called mailModel. To make the data source mailStore work with Grid, he declares a dojox.grid.data.DojoData adapter. You can think of it as a pipe where the data flows in, and the appropriately filtered data comes out for use in a grid. When the app initially starts, there is no folder selected. Hence there are no messages to display. Andy decides to initialize the adapter, but issues a query that will return no items. This has performance benefits, as we'll see in a minute.
/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}The structure is a description of the Grid layout. Structures are composed from views, which are little independently scrollable subgrids called views. Our grid is simple, containing only one view. A cell is Grid's name for a column.
var mailView = {
cells: [[
{name: 'From', field:'sender',width:"25%"},
{name: 'Subject', field:'label',width:"65%"},
{name: 'Date', field:'sent',width:"10%"}
]]
};
var layout = [ mailView ];
The cells property is a two dimensional JavaScript array, hence the double square brackets. In the Grid section, you'll see how to split large amounts of data into subrows, all selectable as one unit. Here we have just one subrow with a small amount of data.
Wiring up the actual Grid is a snap. The Grid widget does all the work for you:
/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}Clicking a row in this grid will display the appropriate message in the bottom area. So Andy stubs out the call to the onRowClick event, which he'll fill in later.
In the folder tree, Andy connects some Dojo code to the onClick event. Once you know the folder name, you simply build a new adapter, set that as the Grid model, and the grid will automatically populate. The nice thing here is the Mail messages are already loaded in the dojo.data store. Building a new Grid model on top of it re-uses the data with a new query without a server round-trip.
/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}So now clicking a folder displays the message list. It's time to go back and fill in onRowClick for the message. This turns out to be fairly trivial:
function displayMailMessage(evt) {
var msg = mailGrid.model.getDatum(evt.rowIndex,6);
dijit.byId("message").setContent(msg);
}
So now he has a message list and a message. Andy looks at his watch. 5 minutes to spare. He can't resist adding one more item - displaying a widget inside a mail message. So he quickly adds a test case to the sample data:
{ type: 'message', id: 'node4.4', folder: 'fun',
label: "paint", sender: "Jack Jackson", sent: "2005-12-16",
text: "what color is good for the new office?Let me know soon"
},
And dojo.require's dijit.ColorPalette. Sure enough, displaying the message automagically displays the palette:
[inline:mail_step8.png]Wow! That's a lot of functionality. In a short amount of code, about 1/2 JavaScript and 1/2 HTML, we have a working email client user interface with:
Sure, the server part needs writing. But that can wait until tomorrow, and it shouldn't be too difficult. Find the right words to get a woman to marry you ... now that's difficult. Andy heads out the door for the train