Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / docs / source / tasks.html
diff --git a/docs/source/tasks.html b/docs/source/tasks.html
new file mode 100644 (file)
index 0000000..1114883
--- /dev/null
@@ -0,0 +1,444 @@
+<html>\r
+<head>\r
+  <title>The source code</title>\r
+    <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
+    <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
+</head>\r
+<body  onload="prettyPrint();">\r
+    <pre class="prettyprint lang-js">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
+       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
+</pre>    \r
+</body>\r
+</html>
\ No newline at end of file