3 * Copyright(c) 2006-2010 Ext JS, Inc.
5 * http://www.extjs.com/license
7 Ext.onReady(function(){
11 // turn off default shadows which look funky in air
12 xg.GridEditor.prototype.shadow = false;
14 var conn = Ext.data.SqlDB.getInstance();
15 conn.open('tasks.db');
17 // the main grid store
18 var taskStore = new TaskStore(conn);
20 // Category store shared by category combos
21 var catStore = new CategoryStore();
26 if(taskStore.getCount() < 1){
27 Ext.Msg.confirm('Create Tasks?', 'Your database is currently empty. Would you like to insert some demo data?',
30 loadDemoTasks(taskStore);
32 catStore.init(taskStore);
35 catStore.init(taskStore);
40 // custom event to notify when a new category is available
41 taskStore.on('newcategory', catStore.addCategory, catStore);
43 // set of event handlers shared by combos to allow them to share
44 // the same local store
47 this.bindStore(catStore);
50 catStore.purgeListeners();
54 var completeColumn = new CompleteColumn();
56 // custom template for the grid header
57 var headerTpl = new Ext.Template(
58 '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
59 '<thead><tr class="x-grid3-hd-row">{cells}</tr></thead>',
60 '<tbody><tr class="new-task-row">',
61 '<td><div id="new-task-icon"></div></td>',
62 '<td><div class="x-small-editor" id="new-task-title"></div></td>',
63 '<td><div class="x-small-editor" id="new-task-cat"></div></td>',
64 '<td><div class="x-small-editor" id="new-task-due"></div></td>',
69 var selections = new Ext.grid.RowSelectionModel();
71 // The main grid in all its configuration option glory
72 var grid = new xg.EditorGridPanel({
77 enableColumnHide:false,
78 enableColumnMove:false,
81 iconCls:'icon-show-all',
84 plugins: completeColumn,
94 editor: new Ext.form.TextField({
102 dataIndex: 'category',
103 editor: new Ext.form.ComboBox({
104 displayField: 'text',
105 triggerAction: 'all',
108 listClass:'x-combo-list-small',
109 listeners: comboEvents
116 renderer: Ext.util.Format.dateRenderer('D m/d/Y'),
117 dataIndex: 'dueDate',
118 groupRenderer: textDate(),
120 editor: new Ext.form.DateField({
126 view: new Ext.grid.GroupingView({
129 emptyText: 'No Tasks to display',
135 getRowClass : function(r){
138 return 'task-completed';
140 if(d.dueDate && d.dueDate.getTime() < new Date().clearTime().getTime()){
141 return 'task-overdue';
148 var viewPanel = new Ext.Panel({
152 contentEl:'task-views',
156 var taskActions = new Ext.Panel({
158 title: 'Task Actions',
160 contentEl:'task-actions',
164 var groupActions = new Ext.Panel({
166 title: 'Task Grouping',
168 contentEl:'task-grouping',
172 var actionPanel = new Ext.Panel({
177 collapseMode: 'mini',
183 items: [taskActions, viewPanel, groupActions]
186 if(Ext.isAir){ // create AIR window
187 var win = new Ext.air.MainWindow({
189 items: [actionPanel, grid],
190 title: 'Simple Tasks',
191 iconCls: 'icon-show-all'
194 var viewport = new Ext.Viewport({
196 items: [actionPanel, grid]
200 var ab = actionPanel.body;
201 ab.on('mousedown', doAction, null, {delegate:'a'});
202 ab.on('click', Ext.emptyFn, null, {delegate:'a', preventDefault:true});
204 grid.on('resize', syncFields);
205 grid.on('columnresize', syncFields);
207 grid.on('afteredit', function(e){
208 if(e.field == 'category'){
209 catStore.addCategory(e.value);
211 if(e.field == taskStore.getGroupState()){
212 taskStore.applyGrouping();
217 grid.on('keydown', function(e){
218 if(e.getKey() == e.DELETE && !grid.editing){
219 actions['action-delete']();
223 selections.on('selectionchange', function(sm){
224 var bd = taskActions.body, c = sm.getCount();
225 bd.select('li:not(#new-task)').setDisplayed(c > 0);
226 bd.select('span.s').setDisplayed(c > 1);
229 // The fields in the grid's header
230 var ntTitle = new Ext.form.TextField({
231 renderTo: 'new-task-title',
232 emptyText: 'Add a task...'
235 var ntCat = new Ext.form.ComboBox({
236 renderTo: 'new-task-cat',
238 displayField: 'text',
239 triggerAction: 'all',
242 listClass:'x-combo-list-small',
243 listeners: comboEvents
246 var ntDue = new Ext.form.DateField({
247 renderTo: 'new-task-due',
253 // syncs the header fields' widths with the grid column widths
254 function syncFields(){
255 var cm = grid.getColumnModel();
256 ntTitle.setSize(cm.getColumnWidth(1)-2);
257 ntCat.setSize(cm.getColumnWidth(2)-4);
258 ntDue.setSize(cm.getColumnWidth(3)-4);
262 var editing = false, focused = false, userTriggered = false;
271 specialkey: function(f, e){
272 if(e.getKey()==e.ENTER){
273 userTriggered = true;
282 ntTitle.on(handlers);
286 ntTitle.on('focus', function(){
296 // when a field in the add bar is blurred, this determines
297 // whether a new task should be created
299 if(editing && !focused){
300 var title = ntTitle.getValue();
301 if(!Ext.isEmpty(title)){
303 taskId: Task.nextId(),
305 dueDate: ntDue.getValue()||'',
306 description: '', // ???
307 category: ntCat.getValue(),
310 ntTitle.setValue('');
311 if(userTriggered){ // if the entered to add the task, then go to a new add automatically
312 userTriggered = false;
313 ntTitle.focus.defer(100, ntTitle);
323 'view-all' : function(){
324 taskStore.applyFilter('all');
325 grid.setTitle('All Tasks', 'icon-show-all');
328 'view-active' : function(){
329 taskStore.applyFilter(false);
330 grid.setTitle('Active Tasks', 'icon-show-active');
333 'view-complete' : function(){
334 taskStore.applyFilter(true);
335 grid.setTitle('Completed Tasks', 'icon-show-complete');
338 'action-new' : function(){
342 'action-complete' : function(){
343 selections.each(function(s){
344 s.set('completed', true);
346 taskStore.applyFilter();
349 'action-active' : function(){
350 selections.each(function(s){
351 s.set('completed', false);
353 taskStore.applyFilter();
356 'action-delete' : function(){
357 Ext.Msg.confirm('Confirm', 'Are you sure you want to delete the selected task(s)?',
360 selections.each(function(s){
367 'group-date' : function(){
368 taskStore.groupBy('dueDate');
371 'group-cat' : function(){
372 taskStore.groupBy('category');
375 'no-group' : function(){
376 taskStore.clearGrouping();
380 function doAction(e, t){
386 // generates a renderer function to be used for textual date groups
388 // create the cache of ranges to be reused
389 var today = new Date().clearTime(true);
390 var year = today.getFullYear();
391 var todayTime = today.getTime();
392 var yesterday = today.add('d', -1).getTime();
393 var tomorrow = today.add('d', 1).getTime();
394 var weekDays = today.add('d', 6).getTime();
395 var lastWeekDays = today.add('d', -6).getTime();
397 return function(date){
401 var notime = date.clearTime(true).getTime();
403 if (notime == todayTime) {
406 if(notime > todayTime){
407 if (notime == tomorrow) {
410 if (notime <= weekDays) {
411 return date.format('l');
414 if(notime == yesterday) {
417 if(notime >= lastWeekDays) {
418 return 'Last ' + date.format('l');
421 return date.getFullYear() == year ? date.format('D m/d') : date.format('D m/d/Y');
426 /* This is used to laod some demo tasks if the task database is empty */
427 function loadDemoTasks(store){
429 // hardcoded demo tasks
430 store.addTask({taskId: Task.nextId(), title:'Start documentation of Ext 2.0', category:'Ext', description:'', dueDate: s.add('d', 21), completed: false});
431 store.addTask({taskId: Task.nextId(), title:'Release Ext 1.l Beta 2', category:'Ext', description:'', dueDate:s.add('d', 2), completed: false});
432 store.addTask({taskId: Task.nextId(), title:'Take wife to see movie', category:'Family', description:'', dueDate:s.add('d', 2), completed: false});
433 store.addTask({taskId: Task.nextId(), title:'Finish task list demo app', category:'Ext', description:'', dueDate:s.add('d', 2), completed: false});
434 store.addTask({taskId: Task.nextId(), title:'Do something other than work', category:'Family', description:'', dueDate:s.add('d', -1), completed: false});
435 store.addTask({taskId: Task.nextId(), title:'Go to the grocery store', category:'Family', description:'', dueDate:s.add('d', -1), completed: true});
436 store.addTask({taskId: Task.nextId(), title:'Reboot my computer', category:'Misc', description:'', dueDate:s, completed: false});
437 store.addTask({taskId: Task.nextId(), title:'Respond to emails', category:'Ext', description:'', dueDate:s, completed: true});