3 <title>The source code</title>
\r
4 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
\r
5 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
\r
7 <body onload="prettyPrint();">
\r
8 <pre class="prettyprint lang-js">// Initialize the state provider
\r
9 Ext.state.Manager.setProvider(new Ext.air.FileProvider({
\r
10 file: 'tasks.state',
\r
11 // if first time running
\r
19 defaultReminder: 480
\r
23 Ext.onReady(function(){
\r
24 Ext.QuickTips.init();
\r
26 // maintain window state automatically
\r
27 var win = new Ext.air.NativeWindow({
\r
29 instance: window.nativeWindow,
\r
30 minimizeToTray: true,
\r
31 trayIcon: 'ext-air/resources/icons/extlogo16.png',
\r
32 trayTip: 'Simple Tasks',
\r
34 text: 'Open Simple Tasks',
\r
35 handler: function(){
\r
40 handler: function(){
\r
41 air.NativeApplication.nativeApplication.exit();
\r
46 tx.data.conn.open('tasks.db');
\r
48 var grid = new TaskGrid();
\r
49 var selections = grid.getSelectionModel();
\r
52 // Shared actions used by Ext toolbars, menus, etc.
\r
54 newTask: new Ext.Action({
\r
56 iconCls: 'icon-active',
\r
57 tooltip: 'New Task',
\r
58 handler: function(){
\r
59 taskHeader.ntTitle.focus();
\r
63 deleteTask: new Ext.Action({
\r
65 iconCls: 'icon-delete-task',
\r
66 tooltip: 'Delete Task',
\r
68 handler: function(){
\r
69 Ext.Msg.confirm('Confirm', 'Are you sure you want to delete the selected task(s)?', function(btn){
\r
71 selections.each(function(s){
\r
72 tx.data.tasks.remove(s);
\r
79 complete: new Ext.Action({
\r
80 itemText: 'Mark Complete',
\r
81 iconCls: 'icon-mark-complete',
\r
82 tooltip: 'Mark Complete',
\r
84 handler: function(){
\r
85 selections.each(function(s){
\r
86 s.set('completed', true);
\r
88 tx.data.tasks.applyFilter();
\r
92 active: new Ext.Action({
\r
93 itemText: 'Mark Active',
\r
94 tooltip: 'Mark Active',
\r
95 iconCls: 'icon-mark-active',
\r
97 handler: function(){
\r
98 selections.each(function(s){
\r
99 s.set('completed', false);
\r
101 tx.data.tasks.applyFilter();
\r
105 newList: new Ext.Action({
\r
106 itemText: 'New List',
\r
107 tooltip: 'New List',
\r
108 iconCls: 'icon-list-new',
\r
109 handler: function(){
\r
110 var id = tx.data.lists.newList(false, tree.getActiveFolderId()).id;
\r
111 tree.startEdit(id, true);
\r
115 deleteList: new Ext.Action({
\r
116 itemText: 'Delete',
\r
117 tooltip: 'Delete List',
\r
118 iconCls: 'icon-list-delete',
\r
120 handler: function(){
\r
121 tree.removeList(tree.getSelectionModel().getSelectedNode());
\r
125 newFolder: new Ext.Action({
\r
126 itemText: 'New Folder',
\r
127 tooltip: 'New Folder',
\r
128 iconCls: 'icon-folder-new',
\r
129 handler: function(){
\r
130 var id = tx.data.lists.newList(true, tree.getActiveFolderId()).id;
\r
131 tree.startEdit(id, true);
\r
135 deleteFolder: new Ext.Action({
\r
136 itemText: 'Delete',
\r
137 tooltip: 'Delete Folder',
\r
138 iconCls: 'icon-folder-delete',
\r
140 handler: function(s){
\r
141 tree.removeList(tree.getSelectionModel().getSelectedNode());
\r
145 quit : new Ext.Action({
\r
147 handler: function(){
\r
148 air.NativeApplication.nativeApplication.exit();
\r
152 pasteAsTask : new Ext.Action({
\r
153 itemText: 'Paste as New Task',
\r
154 tooltip: 'Paste as New Task',
\r
155 iconCls: 'icon-paste-new',
\r
156 handler: function(){
\r
157 if(air.Clipboard.generalClipboard.hasFormat(air.ClipboardFormats.TEXT_FORMAT)){
\r
158 var text = air.Clipboard.generalClipboard.getData(air.ClipboardFormats.TEXT_FORMAT);
\r
159 tx.data.tasks.addTask({
\r
160 taskId: Ext.uniqueId(),
\r
161 title: Ext.util.Format.htmlEncode(text.replace(/[\n\r]/g, '')),
\r
162 dueDate: new Date(),
\r
164 listId: tx.data.getActiveListId(),
\r
169 Ext.Msg.alert('Warning', 'Could not create task. The clipboard is empty.');
\r
174 tx.actions = actions;
\r
176 var menus = Ext.air.SystemMenu;
\r
178 menus.add('File', [
\r
181 actions.newFolder,
\r
184 handler: function(){
\r
185 var importer = new tx.Importer();
\r
186 importer.doImport(function(){
\r
187 tx.data.lists.load();
\r
195 handler: function(){
\r
203 menus.add('Edit', [
\r
204 actions.pasteAsTask
\r
208 var viewMenu = menus.add('View', [{
\r
211 handler: function(){
\r
212 Ext.getCmp('filter').setActiveItem(0);
\r
215 text: 'Active Tasks',
\r
217 handler: function(){
\r
218 Ext.getCmp('filter').setActiveItem(1);
\r
221 text: 'Completed Tasks',
\r
223 handler: function(){
\r
224 Ext.getCmp('filter').setActiveItem(2);
\r
228 menus.add('Help', [{
\r
230 handler: function(){
\r
231 Ext.air.NativeWindowManager.getAboutWindow().activate();
\r
236 var tree = new ListTree({
\r
238 store: tx.data.lists
\r
241 var root = tree.getRootNode();
\r
243 var listSm = tree.getSelectionModel();
\r
245 tx.data.lists.bindTree(tree);
\r
246 tx.data.lists.on('update', function(){
\r
247 tx.data.tasks.applyGrouping();
\r
248 if(grid.titleNode){
\r
249 grid.setTitle(grid.titleNode.text);
\r
253 var tb = new Ext.Toolbar({
\r
258 xtype:'splitbutton',
\r
259 iconCls:'icon-edit',
\r
261 handler: actions.newTask.initialConfig.handler,
\r
262 menu: [actions.newTask, actions.newList, actions.newFolder]
\r
264 actions.deleteTask,
\r
268 actions.pasteAsTask,
\r
274 tooltip:'All Tasks',
\r
276 iconCls:'icon-all',
\r
279 tooltip:'Active Tasks',
\r
281 iconCls:'icon-active',
\r
284 tooltip:'Completed Tasks',
\r
286 iconCls:'icon-complete',
\r
290 change: function(btn, item){
\r
291 tx.data.tasks.applyFilter(item.filter);
\r
292 for (var i = 0; i < 3; i++) {
\r
293 viewMenu.items[i].checked = item.menuIndex === i;
\r
296 delay: 10 // delay gives user instant click feedback before filtering tasks
\r
302 var viewport = new Ext.Viewport({
\r
304 items: [tb, tree, grid]
\r
307 grid.on('keydown', function(e){
\r
308 if(e.getKey() == e.DELETE && !grid.editing){
\r
309 actions.deleteTask.execute();
\r
313 tree.el.on('keydown', function(e){
\r
314 if(e.getKey() == e.DELETE && !tree.editor.editing){
\r
315 actions.deleteList.execute();
\r
319 selections.on('selectionchange', function(sm){
\r
320 var disabled = sm.getCount() < 1;
\r
321 actions.complete.setDisabled(disabled);
\r
322 actions.active.setDisabled(disabled);
\r
323 actions.deleteTask.setDisabled(disabled);
\r
326 var taskHeader = new TaskHeader(grid);
\r
329 win.instance.activate();
\r
331 tx.data.tasks.init();
\r
333 tree.root.select();
\r
335 var loadList = function(listId){
\r
336 var node = tree.getNodeById(listId);
\r
337 if(node && !node.isSelected()){
\r
341 actions.deleteList.setDisabled(!node || !node.attributes.editable);
\r
342 actions.deleteFolder.setDisabled(!node || node.attributes.editable === false || !node.attributes.isFolder);
\r
344 if (node.attributes.isFolder) {
\r
346 node.cascade(function(n){
\r
347 if (!n.attributes.isFolder) {
\r
348 lists.push(n.attributes.id);
\r
351 tx.data.tasks.loadList(lists);
\r
354 tx.data.tasks.loadList(node.id);
\r
356 grid.titleNode = node;
\r
357 grid.setTitle(node.text);
\r
358 grid.setIconClass(node.attributes.iconCls);
\r
362 listSm.on('selectionchange', function(t, node){
\r
363 loadList(node ? node.id : null);
\r
368 if(Ext.state.Manager.get('defaultReminder') === undefined){
\r
369 Ext.state.Manager.set('defaultReminder', 9 * 60); // default to 9am
\r
372 win.on('closing', function(){
\r
373 Ext.air.NativeWindowManager.closeAll();
\r
376 tx.ReminderManager.init();
\r
378 grid.body.on('dragover', function(e){
\r
379 if(e.hasFormat(Ext.air.DragType.TEXT)){
\r
380 e.preventDefault();
\r
384 grid.body.on('drop', function(e){
\r
385 if(e.hasFormat(Ext.air.DragType.TEXT)){
\r
386 var text = e.getData(Ext.air.DragType.TEXT);
\r
389 if(text.indexOf("Subject\t") != -1){
\r
390 var tasks = text.split("\n");
\r
391 for(var i = 1, len = tasks.length; i < len; i++){
\r
392 var data = tasks[i].split("\t");
\r
393 var list = tx.data.lists.findList(data[2]);
\r
394 tx.data.tasks.addTask({
\r
395 taskId: Ext.uniqueId(),
\r
396 title: Ext.util.Format.htmlEncode(data[0]),
\r
397 dueDate: Date.parseDate(data[1], 'D n/j/Y') || '',
\r
399 listId: list ? list.id : tx.data.getActiveListId(),
\r
405 tx.data.tasks.addTask({
\r
406 taskId: Ext.uniqueId(),
\r
407 title: Ext.util.Format.htmlEncode(text),
\r
408 dueDate: new Date(),
\r
410 listId: tx.data.getActiveListId(),
\r
416 air.trace('An error occured trying to import drag drop tasks.');
\r