+++ /dev/null
-/*!
- * Ext JS Library 3.0.3
- * Copyright(c) 2006-2009 Ext JS, LLC
- * licensing@extjs.com
- * http://www.extjs.com/license
- */
-Ext.onReady(function(){\r
- Ext.QuickTips.init();\r
-\r
- var xg = Ext.grid;\r
- // turn off default shadows which look funky in air\r
- xg.GridEditor.prototype.shadow = false;\r
- \r
- var conn = Ext.data.SqlDB.getInstance();\r
- conn.open('tasks.db');\r
- \r
- // the main grid store\r
- var taskStore = new TaskStore(conn);\r
- \r
- // Category store shared by category combos\r
- var catStore = new CategoryStore();\r
- \r
- taskStore.load({\r
- callback: function(){\r
- // first time?\r
- if(taskStore.getCount() < 1){\r
- Ext.Msg.confirm('Create Tasks?', 'Your database is currently empty. Would you like to insert some demo data?', \r
- function(btn){\r
- if(btn == 'yes'){\r
- loadDemoTasks(taskStore); \r
- }\r
- catStore.init(taskStore);\r
- });\r
- }else{\r
- catStore.init(taskStore);\r
- }\r
- }\r
- });\r
-\r
- // custom event to notify when a new category is available\r
- taskStore.on('newcategory', catStore.addCategory, catStore);\r
-\r
- // set of event handlers shared by combos to allow them to share\r
- // the same local store\r
- var comboEvents = {\r
- focus: function(){\r
- this.bindStore(catStore);\r
- },\r
- blur: function(c){\r
- catStore.purgeListeners();\r
- }\r
- }\r
-\r
- var completeColumn = new CompleteColumn();\r
-\r
- // custom template for the grid header\r
- var headerTpl = new Ext.Template(\r
- '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',\r
- '<thead><tr class="x-grid3-hd-row">{cells}</tr></thead>',\r
- '<tbody><tr class="new-task-row">',\r
- '<td><div id="new-task-icon"></div></td>',\r
- '<td><div class="x-small-editor" id="new-task-title"></div></td>',\r
- '<td><div class="x-small-editor" id="new-task-cat"></div></td>',\r
- '<td><div class="x-small-editor" id="new-task-due"></div></td>',\r
- '</tr></tbody>',\r
- "</table>"\r
- );\r
-\r
- var selections = new Ext.grid.RowSelectionModel();\r
-\r
- // The main grid in all its configuration option glory\r
- var grid = new xg.EditorGridPanel({\r
- id:'tasks-grid',\r
- store: taskStore,\r
- sm: selections,\r
- clicksToEdit: 'auto',\r
- enableColumnHide:false,\r
- enableColumnMove:false,\r
- border:false,\r
- title:'All Tasks',\r
- iconCls:'icon-show-all',\r
- region:'center',\r
- \r
- plugins: completeColumn,\r
-\r
- columns: [\r
- completeColumn,\r
- {\r
- header: "Task",\r
- width:400,\r
- sortable: true,\r
- dataIndex: 'title',\r
- id:'task-title',\r
- editor: new Ext.form.TextField({\r
- allowBlank: false\r
- })\r
- },\r
- {\r
- header: "Category",\r
- width:150,\r
- sortable: true,\r
- dataIndex: 'category',\r
- editor: new Ext.form.ComboBox({\r
- displayField: 'text',\r
- triggerAction: 'all',\r
- mode:'local',\r
- selectOnFocus:true,\r
- listClass:'x-combo-list-small',\r
- listeners: comboEvents\r
- })\r
- },\r
- {\r
- header: "Due Date",\r
- width: 150,\r
- sortable: true,\r
- renderer: Ext.util.Format.dateRenderer('D m/d/Y'),\r
- dataIndex: 'dueDate',\r
- groupRenderer: textDate(),\r
- groupName: 'Due',\r
- editor: new Ext.form.DateField({\r
- format : "m/d/Y"\r
- })\r
- }\r
- ],\r
-\r
- view: new Ext.grid.GroupingView({\r
- forceFit:true,\r
- ignoreAdd: true,\r
- emptyText: 'No Tasks to display',\r
-\r
- templates: {\r
- header: headerTpl\r
- },\r
-\r
- getRowClass : function(r){\r
- var d = r.data;\r
- if(d.completed){\r
- return 'task-completed';\r
- }\r
- if(d.dueDate && d.dueDate.getTime() < new Date().clearTime().getTime()){\r
- return 'task-overdue';\r
- }\r
- return '';\r
- }\r
- })\r
- });\r
-\r
- var viewPanel = new Ext.Panel({\r
- frame:true,\r
- title: 'Views',\r
- collapsible:true,\r
- contentEl:'task-views',\r
- titleCollapse: true\r
- });\r
- \r
- var taskActions = new Ext.Panel({\r
- frame:true,\r
- title: 'Task Actions',\r
- collapsible:true,\r
- contentEl:'task-actions',\r
- titleCollapse: true\r
- });\r
- \r
- var groupActions = new Ext.Panel({\r
- frame:true,\r
- title: 'Task Grouping',\r
- collapsible:true,\r
- contentEl:'task-grouping',\r
- titleCollapse: true\r
- });\r
- \r
- var actionPanel = new Ext.Panel({\r
- id:'action-panel',\r
- region:'west',\r
- split:true,\r
- collapsible: true,\r
- collapseMode: 'mini',\r
- header: false,\r
- width:200,\r
- minWidth: 150,\r
- border: false,\r
- baseCls:'x-plain',\r
- items: [taskActions, viewPanel, groupActions]\r
- });\r
-\r
- if(Ext.isAir){ // create AIR window\r
- var win = new Ext.air.MainWindow({\r
- layout:'border',\r
- items: [actionPanel, grid],\r
- title: 'Simple Tasks',\r
- iconCls: 'icon-show-all'\r
- }).render();\r
- }else{\r
- var viewport = new Ext.Viewport({\r
- layout:'border',\r
- items: [actionPanel, grid]\r
- });\r
- }\r
-\r
- var ab = actionPanel.body;\r
- ab.on('mousedown', doAction, null, {delegate:'a'});\r
- ab.on('click', Ext.emptyFn, null, {delegate:'a', preventDefault:true});\r
-\r
- grid.on('resize', syncFields);\r
- grid.on('columnresize', syncFields);\r
-\r
- grid.on('afteredit', function(e){\r
- if(e.field == 'category'){\r
- catStore.addCategory(e.value);\r
- }\r
- if(e.field == taskStore.getGroupState()){\r
- taskStore.applyGrouping();\r
- }\r
-\r
- });\r
-\r
- grid.on('keydown', function(e){\r
- if(e.getKey() == e.DELETE && !grid.editing){\r
- actions['action-delete']();\r
- }\r
- });\r
-\r
- selections.on('selectionchange', function(sm){\r
- var bd = taskActions.body, c = sm.getCount();\r
- bd.select('li:not(#new-task)').setDisplayed(c > 0);\r
- bd.select('span.s').setDisplayed(c > 1);\r
- });\r
-\r
- // The fields in the grid's header\r
- var ntTitle = new Ext.form.TextField({\r
- renderTo: 'new-task-title',\r
- emptyText: 'Add a task...'\r
- });\r
-\r
- var ntCat = new Ext.form.ComboBox({\r
- renderTo: 'new-task-cat',\r
- disabled:true,\r
- displayField: 'text',\r
- triggerAction: 'all',\r
- mode:'local',\r
- selectOnFocus:true,\r
- listClass:'x-combo-list-small',\r
- listeners: comboEvents\r
- });\r
-\r
- var ntDue = new Ext.form.DateField({\r
- renderTo: 'new-task-due',\r
- value: new Date(),\r
- disabled:true,\r
- format : "m/d/Y"\r
- });\r
-\r
- // syncs the header fields' widths with the grid column widths\r
- function syncFields(){\r
- var cm = grid.getColumnModel();\r
- ntTitle.setSize(cm.getColumnWidth(1)-2);\r
- ntCat.setSize(cm.getColumnWidth(2)-4);\r
- ntDue.setSize(cm.getColumnWidth(3)-4);\r
- }\r
- syncFields();\r
-\r
- var editing = false, focused = false, userTriggered = false;\r
- var handlers = {\r
- focus: function(){\r
- focused = true;\r
- },\r
- blur: function(){\r
- focused = false;\r
- doBlur.defer(250);\r
- },\r
- specialkey: function(f, e){\r
- if(e.getKey()==e.ENTER){\r
- userTriggered = true;\r
- e.stopEvent();\r
- f.el.blur();\r
- if(f.triggerBlur){\r
- f.triggerBlur();\r
- }\r
- }\r
- }\r
- }\r
- ntTitle.on(handlers);\r
- ntCat.on(handlers);\r
- ntDue.on(handlers);\r
-\r
- ntTitle.on('focus', function(){\r
- focused = true;\r
- if(!editing){\r
- ntCat.enable();\r
- ntDue.enable();\r
- syncFields();\r
- editing = true;\r
- }\r
- });\r
-\r
- // when a field in the add bar is blurred, this determines\r
- // whether a new task should be created\r
- function doBlur(){\r
- if(editing && !focused){\r
- var title = ntTitle.getValue();\r
- if(!Ext.isEmpty(title)){\r
- taskStore.addTask({\r
- taskId: Task.nextId(),\r
- title: title,\r
- dueDate: ntDue.getValue()||'',\r
- description: '', // ???\r
- category: ntCat.getValue(),\r
- completed: false\r
- });\r
- ntTitle.setValue('');\r
- if(userTriggered){ // if the entered to add the task, then go to a new add automatically\r
- userTriggered = false;\r
- ntTitle.focus.defer(100, ntTitle);\r
- }\r
- }\r
- ntCat.disable();\r
- ntDue.disable();\r
- editing = false;\r
- }\r
- }\r
- \r
- var actions = {\r
- 'view-all' : function(){\r
- taskStore.applyFilter('all');\r
- grid.setTitle('All Tasks', 'icon-show-all');\r
- },\r
- \r
- 'view-active' : function(){\r
- taskStore.applyFilter(false);\r
- grid.setTitle('Active Tasks', 'icon-show-active');\r
- },\r
- \r
- 'view-complete' : function(){\r
- taskStore.applyFilter(true);\r
- grid.setTitle('Completed Tasks', 'icon-show-complete');\r
- },\r
- \r
- 'action-new' : function(){\r
- ntTitle.focus();\r
- },\r
- \r
- 'action-complete' : function(){\r
- selections.each(function(s){\r
- s.set('completed', true);\r
- });\r
- taskStore.applyFilter();\r
- },\r
- \r
- 'action-active' : function(){\r
- selections.each(function(s){\r
- s.set('completed', false);\r
- });\r
- taskStore.applyFilter();\r
- },\r
- \r
- 'action-delete' : function(){\r
- Ext.Msg.confirm('Confirm', 'Are you sure you want to delete the selected task(s)?', \r
- function(btn){\r
- if(btn == 'yes'){\r
- selections.each(function(s){\r
- taskStore.remove(s);\r
- });\r
- }\r
- });\r
- },\r
- \r
- 'group-date' : function(){\r
- taskStore.groupBy('dueDate');\r
- },\r
- \r
- 'group-cat' : function(){\r
- taskStore.groupBy('category');\r
- },\r
- \r
- 'no-group' : function(){\r
- taskStore.clearGrouping();\r
- }\r
- };\r
- \r
- function doAction(e, t){\r
- e.stopEvent();\r
- actions[t.id]();\r
- }\r
- \r
- \r
- // generates a renderer function to be used for textual date groups\r
- function textDate(){\r
- // create the cache of ranges to be reused\r
- var today = new Date().clearTime(true);\r
- var year = today.getFullYear();\r
- var todayTime = today.getTime();\r
- var yesterday = today.add('d', -1).getTime();\r
- var tomorrow = today.add('d', 1).getTime();\r
- var weekDays = today.add('d', 6).getTime();\r
- var lastWeekDays = today.add('d', -6).getTime();\r
-\r
- return function(date){\r
- if(!date) {\r
- return '(No Date)';\r
- }\r
- var notime = date.clearTime(true).getTime();\r
-\r
- if (notime == todayTime) {\r
- return 'Today';\r
- }\r
- if(notime > todayTime){\r
- if (notime == tomorrow) {\r
- return 'Tomorrow';\r
- }\r
- if (notime <= weekDays) {\r
- return date.format('l');\r
- }\r
- }else {\r
- if(notime == yesterday) {\r
- return 'Yesterday';\r
- }\r
- if(notime >= lastWeekDays) {\r
- return 'Last ' + date.format('l');\r
- }\r
- } \r
- return date.getFullYear() == year ? date.format('D m/d') : date.format('D m/d/Y');\r
- }\r
- }\r
-});\r
-\r
-/* This is used to laod some demo tasks if the task database is empty */\r
-function loadDemoTasks(store){\r
- var s = new Date();\r
- // hardcoded demo tasks\r
- store.addTask({taskId: Task.nextId(), title:'Start documentation of Ext 2.0', category:'Ext', description:'', dueDate: s.add('d', 21), completed: false});\r
- store.addTask({taskId: Task.nextId(), title:'Release Ext 1.l Beta 2', category:'Ext', description:'', dueDate:s.add('d', 2), completed: false});\r
- store.addTask({taskId: Task.nextId(), title:'Take wife to see movie', category:'Family', description:'', dueDate:s.add('d', 2), completed: false});\r
- store.addTask({taskId: Task.nextId(), title:'Finish task list demo app', category:'Ext', description:'', dueDate:s.add('d', 2), completed: false});\r
- store.addTask({taskId: Task.nextId(), title:'Do something other than work', category:'Family', description:'', dueDate:s.add('d', -1), completed: false});\r
- store.addTask({taskId: Task.nextId(), title:'Go to the grocery store', category:'Family', description:'', dueDate:s.add('d', -1), completed: true});\r
- store.addTask({taskId: Task.nextId(), title:'Reboot my computer', category:'Misc', description:'', dueDate:s, completed: false});\r
- store.addTask({taskId: Task.nextId(), title:'Respond to emails', category:'Ext', description:'', dueDate:s, completed: true});\r
-}\r
-\r
- \r
-\r