provide installation instructions
[extjs.git] / air / samples / tasks / main.js
1 /*\r
2  * Ext JS Library 0.30\r
3  * Copyright(c) 2006-2009, Ext JS, LLC.\r
4  * licensing@extjs.com\r
5  * \r
6  * http://extjs.com/license\r
7  */\r
8 \r
9 // Initialize the state provider\r
10 Ext.state.Manager.setProvider(new Ext.air.FileProvider({\r
11         file: 'tasks.state',\r
12         // if first time running\r
13         defaultState : {\r
14                 mainWindow : {\r
15                         width:780,\r
16                         height:580,\r
17                         x:10,\r
18                         y:10\r
19                 },\r
20                 defaultReminder: 480\r
21         }\r
22 }));\r
23 \r
24 Ext.onReady(function(){\r
25     Ext.QuickTips.init();\r
26 \r
27         // maintain window state automatically\r
28         var win = new Ext.air.NativeWindow({\r
29                 id: 'mainWindow',\r
30                 instance: window.nativeWindow,\r
31                 minimizeToTray: true,\r
32                 trayIcon: 'ext-air/resources/icons/extlogo16.png',\r
33                 trayTip: 'Simple Tasks',\r
34                 trayMenu : [{\r
35                         text: 'Open Simple Tasks',\r
36                         handler: function(){\r
37                                 win.activate();\r
38                         }\r
39                 }, '-', {\r
40                         text: 'Exit',\r
41                         handler: function(){\r
42                                 air.NativeApplication.nativeApplication.exit();\r
43                         }\r
44                 }]\r
45         });\r
46         \r
47     tx.data.conn.open('tasks.db');\r
48     \r
49     var grid = new TaskGrid();\r
50         var selections = grid.getSelectionModel();\r
51         \r
52         \r
53         // Shared actions used by Ext toolbars, menus, etc.\r
54         var actions = {\r
55                 newTask: new Ext.Action({\r
56                         text: 'New Task',\r
57                         iconCls: 'icon-active',\r
58                         tooltip: 'New Task',\r
59                         handler: function(){\r
60                                 taskHeader.ntTitle.focus();\r
61                         }\r
62                 }),\r
63                 \r
64                 deleteTask: new Ext.Action({\r
65                         itemText: 'Delete',\r
66                         iconCls: 'icon-delete-task',\r
67                         tooltip: 'Delete Task',\r
68                         disabled: true,\r
69                         handler: function(){\r
70                                 Ext.Msg.confirm('Confirm', 'Are you sure you want to delete the selected task(s)?', function(btn){\r
71                                         if (btn == 'yes') {\r
72                                                 selections.each(function(s){\r
73                                                         tx.data.tasks.remove(s);\r
74                                                 });\r
75                                         }\r
76                                 });\r
77                         }\r
78                 }),\r
79                 \r
80                 complete: new Ext.Action({\r
81                         itemText: 'Mark Complete',\r
82                         iconCls: 'icon-mark-complete',\r
83                         tooltip: 'Mark Complete',\r
84                         disabled: true,\r
85                         handler: function(){\r
86                                 selections.each(function(s){\r
87                                         s.set('completed', true);\r
88                                 });\r
89                                 tx.data.tasks.applyFilter();\r
90                         }\r
91                 }),\r
92                 \r
93                 active: new Ext.Action({\r
94                         itemText: 'Mark Active',\r
95                         tooltip: 'Mark Active',\r
96                         iconCls: 'icon-mark-active',\r
97                         disabled: true,\r
98                         handler: function(){\r
99                                 selections.each(function(s){\r
100                                         s.set('completed', false);\r
101                                 });\r
102                                 tx.data.tasks.applyFilter();\r
103                         }\r
104                 }),\r
105                 \r
106                 newList: new Ext.Action({\r
107                         itemText: 'New List',\r
108                         tooltip: 'New List',\r
109                         iconCls: 'icon-list-new',\r
110                         handler: function(){\r
111                                 var id = tx.data.lists.newList(false, tree.getActiveFolderId()).id;\r
112                                 tree.startEdit(id, true);\r
113                         }\r
114                 }),\r
115                 \r
116                 deleteList: new Ext.Action({\r
117                         itemText: 'Delete',\r
118                         tooltip: 'Delete List',\r
119                         iconCls: 'icon-list-delete',\r
120                         disabled: true,\r
121                         handler: function(){\r
122                                 tree.removeList(tree.getSelectionModel().getSelectedNode());\r
123                         }\r
124                 }),\r
125                 \r
126                 newFolder: new Ext.Action({\r
127                         itemText: 'New Folder',\r
128                         tooltip: 'New Folder',\r
129                         iconCls: 'icon-folder-new',\r
130                         handler: function(){\r
131                                 var id = tx.data.lists.newList(true, tree.getActiveFolderId()).id;\r
132                                 tree.startEdit(id, true);\r
133                         }\r
134                 }),\r
135                 \r
136                 deleteFolder: new Ext.Action({\r
137                         itemText: 'Delete',\r
138                         tooltip: 'Delete Folder',\r
139                         iconCls: 'icon-folder-delete',\r
140                         disabled: true,\r
141                         handler: function(s){\r
142                                 tree.removeList(tree.getSelectionModel().getSelectedNode());\r
143                         }\r
144                 }),\r
145                 \r
146                 quit : new Ext.Action({\r
147                         text: 'Exit',\r
148                         handler: function(){\r
149                                 air.NativeApplication.nativeApplication.exit();\r
150                         }\r
151                 }),\r
152                 \r
153                 pasteAsTask : new Ext.Action({\r
154                         itemText: 'Paste as New Task',\r
155                         tooltip: 'Paste as New Task',\r
156             iconCls: 'icon-paste-new',\r
157             handler: function(){\r
158                 if(air.Clipboard.generalClipboard.hasFormat(air.ClipboardFormats.TEXT_FORMAT)){\r
159                                     var text = air.Clipboard.generalClipboard.getData(air.ClipboardFormats.TEXT_FORMAT);\r
160                                         tx.data.tasks.addTask({\r
161                             taskId: Ext.uniqueId(),\r
162                             title: Ext.util.Format.htmlEncode(text.replace(/[\n\r]/g, '')),\r
163                             dueDate: new Date(),\r
164                             description: '', \r
165                             listId: tx.data.getActiveListId(),\r
166                             completed: false, \r
167                                                 reminder: ''\r
168                         });\r
169                                 }else{\r
170                     Ext.Msg.alert('Warning', 'Could not create task. The clipboard is empty.');\r
171                 }\r
172                         }\r
173                 }) \r
174         };\r
175     tx.actions = actions;\r
176 \r
177     var menus = Ext.air.SystemMenu;\r
178         \r
179         menus.add('File', [\r
180                 actions.newTask, \r
181                 actions.newList, \r
182                 actions.newFolder, \r
183                 '-',{\r
184                         text:'Import...',\r
185                         handler: function(){\r
186                                 var importer = new tx.Importer();\r
187                                 importer.doImport(function(){\r
188                                         tx.data.lists.load();\r
189                                         root.reload();\r
190                                         loadList('root');\r
191                                         Ext.Msg.hide();\r
192                                 });\r
193                         }\r
194                 },{\r
195                         text:'Export...',\r
196                         handler: function(){\r
197                                 new tx.Exporter();\r
198                         }\r
199                 },\r
200                 '-', \r
201                 actions.quit\r
202         ]);\r
203 \r
204         menus.add('Edit', [\r
205                 actions.pasteAsTask\r
206         ]);\r
207 \r
208         \r
209     var viewMenu = menus.add('View', [{\r
210         text: 'All Tasks',\r
211         checked: true,\r
212         handler: function(){\r
213             Ext.getCmp('filter').setActiveItem(0);\r
214         }\r
215     },{\r
216         text: 'Active Tasks',\r
217         checked: false,\r
218         handler: function(){\r
219             Ext.getCmp('filter').setActiveItem(1);\r
220         }\r
221     },{\r
222         text: 'Completed Tasks',\r
223         checked: false,\r
224         handler: function(){\r
225             Ext.getCmp('filter').setActiveItem(2);\r
226         }\r
227     }]);\r
228 \r
229     menus.add('Help', [{\r
230         text: 'About',\r
231         handler: function(){\r
232             Ext.air.NativeWindowManager.getAboutWindow().activate();\r
233         }\r
234     }]);\r
235 \r
236 \r
237     var tree = new ListTree({\r
238                 actions: actions,\r
239                 store: tx.data.lists\r
240         });\r
241 \r
242         var root = tree.getRootNode();  \r
243 \r
244         var listSm = tree.getSelectionModel();\r
245         \r
246     tx.data.lists.bindTree(tree);\r
247         tx.data.lists.on('update', function(){\r
248                 tx.data.tasks.applyGrouping();\r
249                 if(grid.titleNode){\r
250                         grid.setTitle(grid.titleNode.text);\r
251                 }\r
252         });\r
253         \r
254         var tb = new Ext.Toolbar({\r
255                 region:'north',\r
256                 id:'main-tb',\r
257                 height:26,\r
258                 items: [{\r
259                                 xtype:'splitbutton',\r
260                                 iconCls:'icon-edit',\r
261                                 text:'New',\r
262                                 handler: actions.newTask.initialConfig.handler,\r
263                                 menu: [actions.newTask, actions.newList, actions.newFolder]\r
264                         },'-',\r
265                         actions.deleteTask,\r
266                         actions.complete,\r
267                         actions.active,\r
268             '-',\r
269             actions.pasteAsTask,\r
270             '->',{\r
271                                 xtype:'switch',\r
272                                 id:'filter',\r
273                 activeItem:0,\r
274                                 items: [{\r
275                                 tooltip:'All Tasks',\r
276                                         filter: 'all',\r
277                                 iconCls:'icon-all',\r
278                                 menuIndex: 0\r
279                 },{\r
280                                 tooltip:'Active Tasks',\r
281                                 filter: false,\r
282                                 iconCls:'icon-active',\r
283                     menuIndex: 1\r
284                             },{\r
285                                 tooltip:'Completed Tasks',\r
286                                         filter: true,\r
287                                 iconCls:'icon-complete',\r
288                     menuIndex: 2\r
289                             }],\r
290                                 listeners: {\r
291                                         change: function(btn, item){\r
292                                                 tx.data.tasks.applyFilter(item.filter);\r
293                                                 for (var i = 0; i < 3; i++) {\r
294                                                         viewMenu.items[i].checked = item.menuIndex === i;\r
295                                                 }\r
296                                         },\r
297                                         delay: 10 // delay gives user instant click feedback before filtering tasks\r
298                                 }\r
299                         }, ' ', ' ', ' '                \r
300                 ]\r
301         });\r
302 \r
303         var viewport = new Ext.Viewport({\r
304         layout:'border',\r
305         items: [tb, tree, grid]\r
306     });\r
307         \r
308         grid.on('keydown', function(e){\r
309          if(e.getKey() == e.DELETE && !grid.editing){\r
310              actions.deleteTask.execute();\r
311          }\r
312     });\r
313 \r
314     tree.el.on('keydown', function(e){\r
315          if(e.getKey() == e.DELETE && !tree.editor.editing){\r
316              actions.deleteList.execute();\r
317          }\r
318     });\r
319 \r
320     selections.on('selectionchange', function(sm){\r
321         var disabled = sm.getCount() < 1;\r
322         actions.complete.setDisabled(disabled);\r
323         actions.active.setDisabled(disabled);\r
324         actions.deleteTask.setDisabled(disabled);\r
325     });\r
326 \r
327         var taskHeader = new TaskHeader(grid);\r
328 \r
329         win.show();\r
330         win.instance.activate();\r
331         \r
332         tx.data.tasks.init();\r
333 \r
334         tree.root.select();\r
335 \r
336         var loadList = function(listId){\r
337                 var node = tree.getNodeById(listId);\r
338                 if(node && !node.isSelected()){\r
339                         node.select();\r
340                         return;\r
341                 }\r
342                 actions.deleteList.setDisabled(!node || !node.attributes.editable);\r
343                 actions.deleteFolder.setDisabled(!node || node.attributes.editable === false || !node.attributes.isFolder);\r
344                 if(node){\r
345                         if (node.attributes.isFolder) {\r
346                                 var lists = [];\r
347                                 node.cascade(function(n){\r
348                                         if (!n.attributes.isFolder) {\r
349                                                 lists.push(n.attributes.id);\r
350                                         }\r
351                                 });\r
352                                 tx.data.tasks.loadList(lists);\r
353                         }\r
354                         else {\r
355                                 tx.data.tasks.loadList(node.id);\r
356                         }\r
357                         grid.titleNode = node;\r
358                         grid.setTitle(node.text);\r
359                         grid.setIconClass(node.attributes.iconCls);\r
360                 }\r
361         }\r
362 \r
363         listSm.on('selectionchange', function(t, node){\r
364                 loadList(node ? node.id : null);\r
365         });\r
366         \r
367         root.reload();\r
368         \r
369         if(Ext.state.Manager.get('defaultReminder') === undefined){\r
370                 Ext.state.Manager.set('defaultReminder', 9 * 60); // default to 9am\r
371         }\r
372         \r
373         win.on('closing', function(){\r
374                 Ext.air.NativeWindowManager.closeAll();\r
375         });\r
376         \r
377         tx.ReminderManager.init();\r
378         \r
379         grid.body.on('dragover', function(e){\r
380                 if(e.hasFormat(Ext.air.DragType.TEXT)){\r
381                         e.preventDefault();\r
382                 }\r
383         });\r
384         \r
385         grid.body.on('drop', function(e){\r
386                 if(e.hasFormat(Ext.air.DragType.TEXT)){\r
387                         var text = e.getData(Ext.air.DragType.TEXT);\r
388                         try{\r
389                                 // from outlook\r
390                                 if(text.indexOf("Subject\t") != -1){\r
391                                         var tasks = text.split("\n");\r
392                                         for(var i = 1, len = tasks.length; i < len; i++){\r
393                                                 var data = tasks[i].split("\t");\r
394                                                 var list = tx.data.lists.findList(data[2]);\r
395                                                 tx.data.tasks.addTask({\r
396                                         taskId: Ext.uniqueId(),\r
397                                         title: Ext.util.Format.htmlEncode(data[0]),\r
398                                         dueDate: Date.parseDate(data[1], 'D n/j/Y') || '',\r
399                                         description: '', \r
400                                         listId: list ? list.id : tx.data.getActiveListId(),\r
401                                         completed: false, \r
402                                                         reminder: ''\r
403                                     });\r
404                                         }\r
405                                 }else{\r
406                                         tx.data.tasks.addTask({\r
407                                 taskId: Ext.uniqueId(),\r
408                                 title: Ext.util.Format.htmlEncode(text),\r
409                                 dueDate: new Date(),\r
410                                 description: '', \r
411                                 listId: tx.data.getActiveListId(),\r
412                                 completed: false, \r
413                                                 reminder: ''\r
414                             });\r
415                                 }\r
416                         }catch(e){\r
417                                 air.trace('An error occured trying to import drag drop tasks.');\r
418                         }\r
419                 }\r
420         });\r
421 });\r
422 \r
423     \r
424 \r