mail.html 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  2. "http://www.w3.org/TR/html4/strict.dtd">
  3. <html>
  4. <head>
  5. <title>Demo Mail Application</title>
  6. <style type="text/css">
  7. @import "../../dojo/resources/dojo.css";
  8. @import "../themes/soria/soria.css";
  9. @import "mail/mail.css";
  10. </style>
  11. <script type="text/javascript" src="../../dojo/dojo.js"
  12. djConfig="isDebug: false, parseOnLoad: true, defaultTestTheme: 'soria'"></script>
  13. <script type="text/javascript" src="../tests/_testCommon.js"></script>
  14. <!--
  15. <script type="text/javascript" src="../dijit.js"></script>
  16. <script type="text/javascript" src="../dijit-all.js"></script>
  17. -->
  18. <script type="text/javascript">
  19. // Use profile builds, if available. Since we use pretty much all of the widgets, just use dijit-all.
  20. // A custom profile would provide some additional savings.
  21. dojo.require("dijit.dijit");
  22. dojo.require("dijit.dijit-all");
  23. dojo.require("dojo.parser");
  24. dojo.require("dojo.data.ItemFileWriteStore");
  25. dojo.require("dijit.dijit");
  26. dojo.require("dijit.Declaration");
  27. dojo.require("dijit.form.Button");
  28. dojo.require("dijit.Menu");
  29. dojo.require("dijit.Tree");
  30. dojo.require("dijit.Tooltip");
  31. dojo.require("dijit.Dialog");
  32. dojo.require("dijit.Toolbar");
  33. dojo.require("dijit._Calendar");
  34. dojo.require("dijit.ColorPalette");
  35. dojo.require("dijit.Editor");
  36. dojo.require("dijit._editor.plugins.LinkDialog");
  37. dojo.require("dijit.ProgressBar");
  38. dojo.require("dijit.form.ComboBox");
  39. dojo.require("dijit.form.CheckBox");
  40. dojo.require("dijit.form.FilteringSelect");
  41. dojo.require("dijit.form.Textarea");
  42. dojo.require("dijit.layout.LayoutContainer");
  43. dojo.require("dijit.layout.SplitContainer");
  44. dojo.require("dijit.layout.AccordionContainer");
  45. dojo.require("dijit.layout.TabContainer");
  46. dojo.require("dijit.layout.ContentPane");
  47. dojo.addOnLoad(function(){
  48. dijit.setWaiRole(dojo.body(), "application");
  49. });
  50. var paneId=1;
  51. // for "new message" tab closing
  52. function testClose(pane,tab){
  53. return confirm("Are you sure you want to leave your changes?");
  54. }
  55. // fake mail download code:
  56. var numMails;
  57. var updateFetchStatus = function(x){
  58. if (x == 0) {
  59. dijit.byId('fakeFetch').update({ indeterminate: false });
  60. return;
  61. }
  62. dijit.byId('fakeFetch').update({ progress: x });
  63. if (x == numMails){
  64. dojo.fadeOut({ node: 'fetchMail', duration:800,
  65. // set progress back to indeterminate. we're cheating, because this
  66. // doesn't actually have any data to "progress"
  67. onEnd: function(){
  68. dijit.byId('fakeFetch').update({ indeterminate: true });
  69. dojo.byId('fetchMail').style.visibility='hidden'; // remove progress bar from tab order
  70. }
  71. }).play();
  72. }
  73. }
  74. var fakeReport = function(percent){
  75. // FIXME: can't set a label on an indeterminate progress bar
  76. // like if(this.indeterminate) { return " connecting."; }
  77. return "Fetching: "+(percent*this.maximum) + " of " + this.maximum + " messages.";
  78. }
  79. var fakeDownload = function(){
  80. dojo.byId('fetchMail').style.visibility='visible';
  81. numMails = Math.floor(Math.random()*10)+1;
  82. dijit.byId('fakeFetch').update({ maximum: numMails, progress:0 });
  83. dojo.fadeIn({ node: 'fetchMail', duration:300 }).play();
  84. for (var i=0; i<=numMails; i++){
  85. setTimeout("updateFetchStatus("+i+")",((i+1)*(Math.floor(Math.random()*100)+400)));
  86. }
  87. }
  88. // fake sending dialog progress bar
  89. var stopSendBar = function(){
  90. dijit.byId('fakeSend').update({indeterminate: false});
  91. dijit.byId('sendDialog').hide();
  92. tabs.selectedChildWidget.onClose = function(){return true;}; // don't want confirm message
  93. tabs.closeChild(tabs.selectedChildWidget);
  94. }
  95. var showSendBar = function(){
  96. dijit.byId('fakeSend').update({ indeterminate: true });
  97. dijit.byId('sendDialog').show();
  98. setTimeout("stopSendBar()", 3000);
  99. }
  100. </script>
  101. </head>
  102. <body class="soria">
  103. <div dojoType="dojo.data.ItemFileWriteStore" jsId="mailStore"
  104. url="mail/mail.json"></div>
  105. <!-- Inline declaration of a table widget (thanks Alex!) -->
  106. <table dojoType="dijit.Declaration"
  107. widgetClass="demo.Table" class="demoTable"
  108. defaults="{ store: null, query: { query: { type: 'message' } }, columns: [ { name: 'From', attribute: 'sender' }, { name: 'Subject', attribute: 'label' }, { name: 'Sent on', attribute: 'sent',
  109. format: function(v){ return dojo.date.locale.format(dojo.date.stamp.fromISOString(v), {selector: 'date'}); }
  110. } ] }">
  111. <thead dojoAttachPoint="head">
  112. <tr dojoAttachPoint="headRow"></tr>
  113. </thead>
  114. <tbody dojoAttachPoint="body">
  115. <tr dojoAttachPoint="row"></tr>
  116. </tbody>
  117. <script type="dojo/method">
  118. dojo.forEach(this.columns, function(item, idx){
  119. var icn = item.className||"";
  120. // add a header for each column
  121. var tth = document.createElement("th");
  122. tth.innerHTML = "<span class='arrowNode'></span> "+ item.name;
  123. tth.className = icn;
  124. dojo.connect(tth, "onclick", dojo.hitch(this, "onSort", idx));
  125. this.headRow.appendChild(tth);
  126. // and fill in the column cell in the template row
  127. this.row.appendChild(document.createElement("td"));
  128. this.row.lastChild.className = icn;
  129. }, this);
  130. this.runQuery();
  131. </script>
  132. <script type="dojo/method" event="onSort" args="index">
  133. var ca = this.columns[index].attribute;
  134. var qs = this.query.sort;
  135. // clobber an existing sort arrow
  136. dojo.query("> th", this.headRow).removeClass("arrowUp").removeClass("arrowDown");
  137. if(qs && qs[0].attribute == ca){
  138. qs[0].descending = !qs[0].descending;
  139. }else{
  140. this.query.sort = [{
  141. attribute: ca,
  142. descending: false
  143. }];
  144. }
  145. var th = dojo.query("> th", this.headRow)[index];
  146. dojo.addClass(th, (this.query.sort[0].descending ? "arrowUp" : "arrowDown"));
  147. this.runQuery();
  148. </script>
  149. <script type="dojo/method" event="runQuery">
  150. this.query.onBegin = dojo.hitch(this, function(){ dojo.query("tr", this.body).orphan(); });
  151. this.query.onItem = dojo.hitch(this, "onItem");
  152. this.query.onComplete = dojo.hitch(this, function(){
  153. dojo.query("tr:nth-child(odd)", this.body).addClass("oddRow");
  154. dojo.query("tr:nth-child(even)", this.body).removeClass("oddRow");
  155. });
  156. this.store.fetch(this.query);
  157. </script>
  158. <script type="dojo/method" event="onItem" args="item">
  159. var tr = this.row.cloneNode(true);
  160. dojo.query("td", tr).forEach(function(n, i, a){
  161. var tc = this.columns[i];
  162. var tv = this.store.getValue(item, tc.attribute)||"";
  163. if(tc.format){ tv = tc.format(tv, item, this.store); }
  164. n.innerHTML = tv;
  165. }, this);
  166. this.body.appendChild(tr);
  167. dojo.connect(tr, "onclick", this, function(){ this.onClick(item); });
  168. </script>
  169. </table>
  170. <!-- Inline declaration for programmatically created "New Message" tabs -->
  171. <div dojoType="dijit.Declaration"
  172. widgetClass="mail.NewMessage">
  173. <div dojoType="dijit.layout.LayoutContainer" dojoAttachPoint="container" title="Composing..." closeable="true">
  174. <div dojoType="dijit.layout.LayoutContainer" layoutAlign="top" style="overflow: visible; z-index: 10; color:#666; ">
  175. <table width=100%>
  176. <tr style="padding-top:5px;">
  177. <td style="padding-left:20px; padding-right: 8px; text-align:right;"><label for="${id}_to">To:</label></td>
  178. <td width=100%>
  179. <select dojoType="dijit.form.ComboBox" id="${id}_to" hasDownArrow="false">
  180. <option></option>
  181. <option>adam@yahoo.com</option>
  182. <option>barry@yahoo.com</option>
  183. <option>bob@yahoo.com</option>
  184. <option>cal@yahoo.com</option>
  185. <option>chris@yahoo.com</option>
  186. <option>courtney@yahoo.com</option>
  187. </select>
  188. </td>
  189. </tr>
  190. <tr>
  191. <td style="padding-left: 20px; padding-right:8px; text-align:right;"><label for="${id}_subject">Subject:</label></td>
  192. <td width=100%>
  193. <select dojoType="dijit.form.ComboBox" id="${id}_subject" hasDownArrow="false">
  194. <option></option>
  195. <option>progress meeting</option>
  196. <option>reports</option>
  197. <option>lunch</option>
  198. <option>vacation</option>
  199. <option>status meeting</option>
  200. </select>
  201. </td>
  202. </tr>
  203. </table>
  204. <hr noshade size="1">
  205. </div>
  206. <!-- new messase part -->
  207. <div dojoType="dijit.layout.LayoutContainer" layoutAlign="client">
  208. <!-- FIXME: editor as direct widget here doesn't init -->
  209. <div dojoType="dijit.layout.ContentPane" href="mail/newMail.html"></div>
  210. </div>
  211. <div dojoType="dijit.layout.LayoutContainer" layoutAlign="bottom" align=center>
  212. <button dojoType="dijit.form.Button" iconClass="mailIconOk"
  213. >Send
  214. <script type="dojo/method" event="onClick">
  215. var toField = dojo.byId("${id}_to");
  216. if (toField.value == ""){
  217. alert("Please enter a recipient address");
  218. }else{
  219. showSendBar();
  220. }
  221. </script>
  222. </button>
  223. <button dojoType="dijit.form.Button" iconClass="mailIconCancel"
  224. >Cancel
  225. <script type="dojo/method" event="onClick">
  226. tabs.closeChild(tabs.selectedChildWidget);
  227. </script>
  228. </button>
  229. </div>
  230. </div>
  231. </div>
  232. <div dojoType="dijit.layout.LayoutContainer" id="main">
  233. <!-- toolbar with new mail button, etc. -->
  234. <div dojoType="dijit.Toolbar" layoutAlign="top" style="height:25px;">
  235. <div id="getMail" dojoType="dijit.form.ComboButton"
  236. iconClass="mailIconGetMail" optionsTitle="Mail Source Options">
  237. <script type="dojo/method" event="onClick">
  238. fakeDownload();
  239. </script>
  240. <span>Get Mail</span>
  241. <ul dojoType="dijit.Menu">
  242. <li dojoType="dijit.MenuItem" iconClass="mailIconGetMail">Yahoo</li>
  243. <li dojoType="dijit.MenuItem" iconClass="mailIconGetMail">GMail</li>
  244. </ul>
  245. </div>
  246. <span dojoType="dijit.Tooltip" connectId="getMail">Click to download new mail.</span>
  247. <button
  248. id="newMsg" dojoType="dijit.form.Button"
  249. iconClass="mailIconNewMessage">
  250. New Message
  251. <script type="dojo/method" event="onClick">
  252. /* make a new tab for composing the message */
  253. var newTab = new mail.NewMessage({id: "new"+paneId }).container;
  254. dojo.mixin(newTab,
  255. {
  256. title: "New Message #" + paneId++,
  257. closable: true,
  258. onClose: testClose
  259. }
  260. );
  261. tabs.addChild(newTab);
  262. tabs.selectChild(newTab);
  263. </script>
  264. </button>
  265. <span dojoType="dijit.Tooltip" connectId="newMsg">Click to compose new message.</span>
  266. <button id="options" dojoType="dijit.form.Button" iconClass="mailIconOptions">
  267. Options
  268. <script type="dojo/method" event="onClick">
  269. dijit.byId('optionsDialog').show();
  270. </script>
  271. </button>
  272. <div dojoType="dijit.Tooltip" connectId="options">Set various options</div>
  273. </div>
  274. <div dojoType="dijit.layout.TabContainer" id="tabs" jsId="tabs" layoutAlign="client">
  275. <!-- main section with tree, table, and preview -->
  276. <div dojoType="dijit.layout.SplitContainer"
  277. orientation="horizontal"
  278. sizerWidth="5"
  279. activeSizing="0"
  280. title="Inbox"
  281. >
  282. <div dojoType="dijit.layout.AccordionContainer" sizeMin="20" sizeShare="20">
  283. <div dojoType="dijit.layout.AccordionPane" title="Folders">
  284. <div dojoType="dijit.Tree" id="mytree" store="mailStore"
  285. labelAttr="label" childrenAttr="folders" query="{type:'folder'}" label="Folders">
  286. <script type="dojo/method" event="onClick" args="item">
  287. if(!item){
  288. return; // top level node in tree doesn't correspond to any item
  289. }
  290. /* filter the message list to messages in this folder */
  291. table.query.query = {
  292. type: "message",
  293. folder: mailStore.getValue(item, "id")
  294. };
  295. table.runQuery();
  296. </script>
  297. <script type="dojo/method" event="getIconClass" args="item">
  298. return (item && mailStore.getValue(item, "icon")) || "mailIconFolderDocuments";
  299. </script>
  300. </div>
  301. </div>
  302. <div dojoType="dijit.layout.AccordionPane" title="Address Book">
  303. <span dojoType="demo.Table" store="mailStore"
  304. query="{ query: { type: 'address' }, columns: [ {name: 'User name', attribute: 'label'} ], sort: [ { attribute: 'label' } ] }"
  305. id="addresses" style="width: 100%">
  306. <script type="dojo/method" event="preamble">
  307. this.query = { type: "address" };
  308. this.columns = [
  309. {
  310. name: "Name",
  311. attribute: "label"
  312. }
  313. ];
  314. </script>
  315. <script type="dojo/method" event="onClick" args="item">
  316. table.query.query.sender = mailStore.getValue(item, "sender");
  317. delete table.query.query.folder;
  318. table.runQuery();
  319. </script>
  320. </span>
  321. </div>
  322. </div> <!-- end of Accordion -->
  323. <div dojoType="dijit.layout.SplitContainer"
  324. id="rightPane"
  325. orientation="vertical"
  326. sizerWidth="5"
  327. activeSizing="0"
  328. sizeMin="50" sizeShare="85"
  329. >
  330. <div id="listPane" dojoType="dijit.layout.ContentPane" sizeMin="20" sizeShare="20">
  331. <span dojoType="demo.Table" store="mailStore"
  332. query="{ query: { type: 'message' }, sort: [ { attribute: 'label' } ] }"
  333. id="foo" jsId="table" style="width: 100%">
  334. <script type="dojo/method" event="onClick" args="item">
  335. var sender = this.store.getValue(item, "sender");
  336. var subject = this.store.getValue(item, "label");
  337. var sent = dojo.date.locale.format(
  338. dojo.date.stamp.fromISOString(this.store.getValue(item, "sent")),
  339. {formatLength: "long", selector: "date"});
  340. var text = this.store.getValue(item, "text");
  341. var messageInner = "<span class='messageHeader'>From: " + sender + "<br>" +
  342. "Subject: "+ subject + "<br>" +
  343. "Date: " + sent + "<br><br></span>" +
  344. text;
  345. dijit.byId("message").setContent(messageInner);
  346. </script>
  347. </span>
  348. </div>
  349. <div id="message" dojoType="dijit.layout.ContentPane" sizeMin="20" sizeShare="80">
  350. <p>
  351. This is a simple application mockup showing some of the dojo widgets:
  352. </p>
  353. <ul>
  354. <li>layout widgets: SplitContainer, LayoutContainer, AccordionContainer</li>
  355. <li>TooltipDialog, Tooltip</li>
  356. <li>Tree</li>
  357. <li>form widgets: Button, DropDownButton, ComboButton, FilteringSelect, ComboBox</li>
  358. <li>Editor</li>
  359. </ul>
  360. <p>
  361. The message list above originally contains all the messages, but you can filter it
  362. by clicking on items in the left Accordion.
  363. Then click on the messages in the above list to display them.
  364. There's no server running, so the app is just a facade and it doesn't really do anything.
  365. <!-- TODO: delete button (we can delete since we are using ItemFileWriteStore -->
  366. </p>
  367. <p>
  368. <span style="font-family: 'Comic Sans MS',Textile,cursive; color: blue; font-style: italic;">-- Bill</span>
  369. </p>
  370. </div>
  371. </div> <!-- end of vertical SplitContainer -->
  372. </div> <!-- end of horizontal SplitContainer -->
  373. </div> <!-- end of TabContainer -->
  374. <div dojoType="dijit.layout.ContentPane" layoutAlign="bottom" id="footer" align="left">
  375. <span style="float:right;">DojoMail v1.0 (demo only)</span>
  376. <div id="fetchMail" style="opacity:0;visibility:hidden">
  377. <div annotate="true" id="fakeFetch" dojoType="dijit.ProgressBar" style="height:15px; width:275px;" indeterminate="true" report="fakeReport"></div>
  378. </div>
  379. </div>
  380. </div> <!-- end of Layoutcontainer -->
  381. <div dojoType="dijit.Dialog" id="optionsDialog" title="Options:">
  382. <table>
  383. <tr><td style="text-align:right;"><label for="option1">Transport type:</label></td><td>
  384. <select id="option1" dojoType="dijit.form.FilteringSelect">
  385. <option value="pop3">POP3</option>
  386. <option value="imap">IMAP</option>
  387. </select></td></tr>
  388. <tr><td style="text-align:right;"><label for="option2">Server:</label></td><td><input id="option2" dojoType="dijit.form.TextBox" type="text">
  389. </td></tr>
  390. <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>
  391. <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>
  392. <tr><td colspan="2" style="text-align:center;">
  393. <button dojoType="dijit.form.Button" type="submit" iconClass="mailIconOk">OK</button>
  394. <button dojoType="dijit.form.Button" type="submit" iconClass="mailIconCancel">Abort</button>
  395. </td></tr>
  396. </table>
  397. </div>
  398. <div dojoType="dijit.Dialog" id="sendDialog" title="Sending Mail">
  399. <div id="sendMailBar" style="text-align:center">
  400. <div id="fakeSend" dojoType="dijit.ProgressBar" style="height:15px; width:175px;" indeterminate="true" ></div>
  401. </div>
  402. <div>
  403. </body>
  404. </html>