1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
2 "http://www.w3.org/TR/html4/strict.dtd">
5 <title>Demo Mail Application</title>
7 <style type="text/css">
8 @import "../../dojo/resources/dojo.css";
9 @import "../themes/soria/soria.css";
10 @import "mail/mail.css";
12 <style type="text/css">
13 #inbox .dijitSplitterH { height: 5px }
14 #inbox .dijitSplitterV { width: 5px }
17 <script type="text/javascript" src="../../dojo/dojo.js"
18 djConfig="isDebug: false, parseOnLoad: true, defaultTestTheme: 'soria'"></script>
19 <script type="text/javascript" src="../tests/_testCommon.js"></script>
21 <script type="text/javascript" src="../dijit.js"></script>
22 <script type="text/javascript" src="../dijit-all.js" charset="utf-8"></script>
24 <script type="text/javascript">
25 // Use profile builds, if available. Since we use pretty much all of the widgets, just use dijit-all.
26 // A custom profile would provide some additional savings.
27 dojo.require("dijit.dijit");
28 dojo.require("dijit.dijit-all");
30 dojo.require("dojo.parser");
31 dojo.require("dojo.data.ItemFileWriteStore");
33 dojo.require("dijit.dijit");
34 dojo.require("dijit.Declaration");
35 dojo.require("dijit.form.Button");
36 dojo.require("dijit.Menu");
37 dojo.require("dijit.Tree");
38 dojo.require("dijit.Tooltip");
39 dojo.require("dijit.Dialog");
40 dojo.require("dijit.Toolbar");
41 dojo.require("dijit._Calendar");
42 dojo.require("dijit.ColorPalette");
43 dojo.require("dijit.Editor");
44 dojo.require("dijit._editor.plugins.LinkDialog");
45 dojo.require("dijit.ProgressBar");
47 dojo.require("dijit.form.ComboBox");
48 dojo.require("dijit.form.CheckBox");
49 dojo.require("dijit.form.FilteringSelect");
50 dojo.require("dijit.form.Textarea");
52 dojo.require("dijit.layout.BorderContainer");
53 dojo.require("dijit.layout.AccordionContainer");
54 dojo.require("dijit.layout.TabContainer");
55 dojo.require("dijit.layout.ContentPane");
57 dojo.addOnLoad(function(){
58 dijit.setWaiRole(dojo.body(), "application");
63 // for "new message" tab closing
64 function testClose(pane,tab){
65 return confirm("Are you sure you want to leave your changes?");
68 // fake mail download code:
70 var updateFetchStatus = function(x){
72 dijit.byId('fakeFetch').update({ indeterminate: false });
75 dijit.byId('fakeFetch').update({ progress: x });
77 dojo.fadeOut({ node: 'fetchMail', duration:800,
78 // set progress back to indeterminate. we're cheating, because this
79 // doesn't actually have any data to "progress"
81 dijit.byId('fakeFetch').update({ indeterminate: true });
82 dojo.byId('fetchMail').style.visibility='hidden'; // remove progress bar from tab order
87 var fakeReport = function(percent){
88 // FIXME: can't set a label on an indeterminate progress bar
89 // like if(this.indeterminate) { return " connecting."; }
90 return dojo.string.substitute("Fetching: ${0} of ${1} messages.", [percent*this.maximum, this.maximum]);
92 var fakeDownload = function(){
93 dojo.byId('fetchMail').style.visibility='visible';
94 numMails = Math.floor(Math.random()*10)+1;
95 dijit.byId('fakeFetch').update({ maximum: numMails, progress:0 });
96 dojo.fadeIn({ node: 'fetchMail', duration:300 }).play();
97 for (var i=0; i<=numMails; i++){
98 setTimeout(function(){updateFetchStatus(i);},((i+1)*(Math.floor(Math.random()*100)+400)));
101 // fake sending dialog progress bar
102 var stopSendBar = function(){
103 dijit.byId('fakeSend').update({indeterminate: false});
104 dijit.byId('sendDialog').hide();
105 tabs.selectedChildWidget.onClose = function(){return true;}; // don't want confirm message
106 tabs.closeChild(tabs.selectedChildWidget);
109 var showSendBar = function(){
110 dijit.byId('fakeSend').update({ indeterminate: true });
111 dijit.byId('sendDialog').show();
112 setTimeout(function(){stopSendBar();}, 3000);
118 <div dojoType="dojo.data.ItemFileWriteStore" jsId="mailStore"
119 url="mail/mail.json"></div>
121 <!-- Inline declaration of a table widget (thanks Alex!) -->
123 <table dojoType="dijit.Declaration"
124 widgetClass="demo.Table" class="demoTable"
125 defaults="{ store: null, query: { query: { type: 'message' } }, columns: [ { name: 'From', attribute: 'sender' }, { name: 'Subject', attribute: 'label' }, { name: 'Sent on', attribute: 'sent',
126 format: function(v){ return dojo.date.locale.format(dojo.date.stamp.fromISOString(v), {selector: 'date'}); }
128 <thead dojoAttachPoint="head">
129 <tr dojoAttachPoint="headRow"></tr>
131 <tbody dojoAttachPoint="body">
132 <tr dojoAttachPoint="row"></tr>
135 <script type="dojo/method">
136 dojo.forEach(this.columns, function(item, idx){
137 var icn = item.className||"";
138 // add a header for each column
139 var tth = document.createElement("th");
140 tth.innerHTML = "<span class='arrowNode'></span> "+ item.name;
142 dojo.connect(tth, "onclick", dojo.hitch(this, "onSort", idx));
143 this.headRow.appendChild(tth);
145 // and fill in the column cell in the template row
146 this.row.appendChild(document.createElement("td"));
147 this.row.lastChild.className = icn;
151 <script type="dojo/method" event="onSort" args="index">
152 var ca = this.columns[index].attribute;
153 var qs = this.query.sort;
154 // clobber an existing sort arrow
155 dojo.query("> th", this.headRow).removeClass("arrowUp").removeClass("arrowDown");
156 if(qs && qs[0].attribute == ca){
157 qs[0].descending = !qs[0].descending;
164 var th = dojo.query("> th", this.headRow)[index];
165 dojo.addClass(th, (this.query.sort[0].descending ? "arrowUp" : "arrowDown"));
168 <script type="dojo/method" event="runQuery">
169 this.query.onBegin = dojo.hitch(this, function(){ dojo.query("tr", this.body).orphan(); });
170 this.query.onItem = dojo.hitch(this, "onItem");
171 this.query.onComplete = dojo.hitch(this, function(){
172 dojo.query("tr:nth-child(odd)", this.body).addClass("oddRow");
173 dojo.query("tr:nth-child(even)", this.body).removeClass("oddRow");
175 this.store.fetch(this.query);
177 <script type="dojo/method" event="onItem" args="item">
178 var tr = this.row.cloneNode(true);
179 dojo.query("td", tr).forEach(function(n, i, a){
180 var tc = this.columns[i];
181 var tv = this.store.getValue(item, tc.attribute)||"";
182 if(tc.format){ tv = tc.format(tv, item, this.store); }
185 this.body.appendChild(tr);
186 dojo.connect(tr, "onclick", this, function(){ this.onClick(item); });
190 <!-- Inline declaration for programmatically created "New Message" tabs -->
191 <div dojoType="dijit.Declaration"
192 widgetClass="mail.NewMessage">
193 <div dojoType="dijit.layout.BorderContainer" dojoAttachPoint="container" title="Composing..." closeable="true">
194 <div dojoType="dijit.layout.ContentPane" region="top" style="height:60px; overflow: visible; z-index: 10; color:#666;">
196 <tr style="padding-top:5px;">
197 <td style="padding-left:20px; padding-right: 8px; text-align:right;"><label for="${id}_to">To:</label></td>
199 <select dojoType="dijit.form.ComboBox" id="${id}_to" hasDownArrow="false">
201 <option>adam@yahoo.com</option>
202 <option>barry@yahoo.com</option>
203 <option>bob@yahoo.com</option>
204 <option>cal@yahoo.com</option>
205 <option>chris@yahoo.com</option>
206 <option>courtney@yahoo.com</option>
211 <td style="padding-left: 20px; padding-right:8px; text-align:right;"><label for="${id}_subject">Subject:</label></td>
213 <select dojoType="dijit.form.ComboBox" id="${id}_subject" hasDownArrow="false">
215 <option>progress meeting</option>
216 <option>reports</option>
217 <option>lunch</option>
218 <option>vacation</option>
219 <option>status meeting</option>
224 <hr noshade size="1">
227 <!-- new message part -->
228 <!-- FIXME: editor as direct widget here doesn't init -->
229 <div dojoType="dijit.layout.ContentPane" region="center" href="mail/newMail.html"></div>
231 <div dojoType="dijit.layout.ContentPane" region="bottom" style="height:32px" align="center">
232 <button dojoType="dijit.form.Button" iconClass="mailIconOk"
234 <script type="dojo/method" event="onClick">
235 var toField = dojo.byId("${id}_to");
236 if (toField.value == ""){
237 alert("Please enter a recipient address");
243 <button dojoType="dijit.form.Button" iconClass="mailIconCancel"
245 <script type="dojo/method" event="onClick">
246 tabs.closeChild(tabs.selectedChildWidget);
254 <div dojoType="dijit.layout.BorderContainer" id="main">
256 <!-- toolbar with new mail button, etc. -->
257 <div dojoType="dijit.Toolbar" region="top" style="height:25px;">
258 <div id="getMail" dojoType="dijit.form.ComboButton"
259 iconClass="mailIconGetMail" optionsTitle="Mail Source Options">
260 <script type="dojo/method" event="onClick">
263 <span>Get Mail</span>
264 <ul dojoType="dijit.Menu">
265 <li dojoType="dijit.MenuItem" iconClass="mailIconGetMail">Yahoo</li>
266 <li dojoType="dijit.MenuItem" iconClass="mailIconGetMail">GMail</li>
269 <span dojoType="dijit.Tooltip" connectId="getMail">Click to download new mail.</span>
272 id="newMsg" dojoType="dijit.form.Button"
273 iconClass="mailIconNewMessage">
275 <script type="dojo/method" event="onClick">
276 /* make a new tab for composing the message */
277 var newTab = new mail.NewMessage({id: "new"+paneId }).container;
280 title: "New Message #" + paneId++,
285 tabs.addChild(newTab);
286 tabs.selectChild(newTab);
289 <span dojoType="dijit.Tooltip" connectId="newMsg">Click to compose new message.</span>
291 <button id="options" dojoType="dijit.form.Button" iconClass="mailIconOptions">
293 <script type="dojo/method" event="onClick">
294 dijit.byId('optionsDialog').show();
297 <div dojoType="dijit.Tooltip" connectId="options">Set various options</div>
300 <div dojoType="dijit.layout.TabContainer" id="tabs" jsId="tabs" region="center">
301 <!-- main section with tree, table, and preview -->
302 <div dojoType="dijit.layout.BorderContainer" id="inbox" title="Inbox" design="sidebar">
303 <div dojoType="dijit.layout.AccordionContainer" region="leading" minSize="20" style="width:20%;" splitter="true">
304 <div dojoType="dijit.layout.AccordionPane" title="Folders">
305 <div dojoType="dijit.Tree" id="mytree" store="mailStore"
306 childrenAttr="folders" query="{type:'folder'}" label="Folders">
307 <script type="dojo/method" event="onClick" args="item">
309 return; // top level node in tree doesn't correspond to any item
311 /* filter the message list to messages in this folder */
312 table.query.query = {
314 folder: mailStore.getValue(item, "id")
318 <script type="dojo/method" event="getIconClass" args="item">
319 return (item && mailStore.getValue(item, "icon")) || "mailIconFolderDocuments";
323 <div dojoType="dijit.layout.AccordionPane" title="Address Book">
324 <span dojoType="demo.Table" store="mailStore"
325 query="{ query: { type: 'address' }, columns: [ {name: 'User name', attribute: 'label'} ], sort: [ { attribute: 'label' } ] }"
326 id="addresses" style="width: 100%">
327 <script type="dojo/method" event="preamble">
328 this.query = { type: "address" };
336 <script type="dojo/method" event="onClick" args="item">
337 table.query.query.sender = mailStore.getValue(item, "sender");
338 delete table.query.query.folder;
343 </div> <!-- end of Accordion -->
345 <!-- list of messages pane -->
346 <div id="listPane" dojoType="dijit.layout.ContentPane" region="top" minSize="20" style="height:134px;" splitter="true">
347 <span dojoType="demo.Table" store="mailStore"
348 query="{ query: { type: 'message' }, sort: [ { attribute: 'label' } ] }"
349 id="foo" jsId="table" style="width: 100%">
350 <script type="dojo/method" event="onClick" args="item">
351 var sender = this.store.getValue(item, "sender");
352 var subject = this.store.getValue(item, "label");
353 var sent = dojo.date.locale.format(
354 dojo.date.stamp.fromISOString(this.store.getValue(item, "sent")),
355 {formatLength: "long", selector: "date"});
356 var text = this.store.getValue(item, "text");
357 var messageInner = "<span class='messageHeader'>From: " + sender + "<br>" +
358 "Subject: "+ subject + "<br>" +
359 "Date: " + sent + "<br><br></span>" +
361 dijit.byId("message").setContent(messageInner);
364 </div> <!-- end of listPane -->
366 <!-- message preview pane -->
367 <div id="message" dojoType="dijit.layout.ContentPane" region="center" minSize="20">
369 This is a simple application mockup showing some of the dojo widgets:
372 <li>layout widgets: BorderContainer, AccordionContainer</li>
373 <li>TooltipDialog, Tooltip</li>
375 <li>form widgets: Button, DropDownButton, ComboButton, FilteringSelect, ComboBox</li>
379 The message list above originally contains all the messages, but you can filter it
380 by clicking on items in the left Accordion.
381 Then click on the messages in the above list to display them.
382 There's no server running, so the app is just a facade and it doesn't really do anything.
383 <!-- TODO: delete button (we can delete since we are using ItemFileWriteStore -->
386 <span style="font-family: 'Comic Sans MS',Textile,cursive; color: blue; font-style: italic;">-- Bill</span>
388 </div> <!-- end of "message" -->
390 </div> <!-- end of inbox -->
391 </div> <!-- end of TabContainer -->
393 <div dojoType="dijit.layout.ContentPane" region="bottom" id="footer" align="left">
394 <span style="float:right;">DojoMail v1.0 (demo only)</span>
395 <div id="fetchMail" style="opacity:0;visibility:hidden">
396 <div annotate="true" id="fakeFetch" dojoType="dijit.ProgressBar" style="height:15px; width:275px;" indeterminate="true" report="fakeReport"></div>
399 </div> <!-- end of main -->
401 <div dojoType="dijit.Dialog" id="optionsDialog" title="Options:">
403 <tr><td style="text-align:right;"><label for="option1">Transport type:</label></td><td>
404 <select id="option1" dojoType="dijit.form.FilteringSelect">
405 <option value="pop3">POP3</option>
406 <option value="imap">IMAP</option>
408 <tr><td style="text-align:right;"><label for="option2">Server:</label></td><td><input id="option2" dojoType="dijit.form.TextBox" type="text">
411 <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>
412 <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>
414 <tr><td colspan="2" style="text-align:center;">
415 <button dojoType="dijit.form.Button" type="submit" iconClass="mailIconOk">OK</button>
416 <button dojoType="dijit.form.Button" type="submit" iconClass="mailIconCancel">Abort</button>
420 <div dojoType="dijit.Dialog" id="sendDialog" title="Sending Mail">
421 <div id="sendMailBar" style="text-align:center">
422 <div id="fakeSend" dojoType="dijit.ProgressBar" style="height:15px; width:175px;" indeterminate="true" ></div>