3
* Copyright(c) 2006-2009 Ext JS, LLC
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',
182
items: [taskActions, viewPanel, groupActions]
185
if(Ext.isAir){ // create AIR window
186
var win = new Ext.air.MainWindow({
188
items: [actionPanel, grid],
189
title: 'Simple Tasks',
190
iconCls: 'icon-show-all'
193
var viewport = new Ext.Viewport({
195
items: [actionPanel, grid]
199
var ab = actionPanel.body;
200
ab.on('mousedown', doAction, null, {delegate:'a'});
201
ab.on('click', Ext.emptyFn, null, {delegate:'a', preventDefault:true});
203
grid.on('resize', syncFields);
204
grid.on('columnresize', syncFields);
206
grid.on('afteredit', function(e){
207
if(e.field == 'category'){
208
catStore.addCategory(e.value);
210
if(e.field == taskStore.getGroupState()){
211
taskStore.applyGrouping();
216
grid.on('keydown', function(e){
217
if(e.getKey() == e.DELETE && !grid.editing){
218
actions['action-delete']();
222
selections.on('selectionchange', function(sm){
223
var bd = taskActions.body, c = sm.getCount();
224
bd.select('li:not(#new-task)').setDisplayed(c > 0);
225
bd.select('span.s').setDisplayed(c > 1);
228
// The fields in the grid's header
229
var ntTitle = new Ext.form.TextField({
230
renderTo: 'new-task-title',
231
emptyText: 'Add a task...'
234
var ntCat = new Ext.form.ComboBox({
235
renderTo: 'new-task-cat',
237
displayField: 'text',
238
triggerAction: 'all',
241
listClass:'x-combo-list-small',
242
listeners: comboEvents
245
var ntDue = new Ext.form.DateField({
246
renderTo: 'new-task-due',
252
// syncs the header fields' widths with the grid column widths
253
function syncFields(){
254
var cm = grid.getColumnModel();
255
ntTitle.setSize(cm.getColumnWidth(1)-2);
256
ntCat.setSize(cm.getColumnWidth(2)-4);
257
ntDue.setSize(cm.getColumnWidth(3)-4);
261
var editing = false, focused = false, userTriggered = false;
270
specialkey: function(f, e){
271
if(e.getKey()==e.ENTER){
272
userTriggered = true;
281
ntTitle.on(handlers);
285
ntTitle.on('focus', function(){
295
// when a field in the add bar is blurred, this determines
296
// whether a new task should be created
298
if(editing && !focused){
299
var title = ntTitle.getValue();
300
if(!Ext.isEmpty(title)){
302
taskId: Task.nextId(),
304
dueDate: ntDue.getValue()||'',
305
description: '', // ???
306
category: ntCat.getValue(),
309
ntTitle.setValue('');
310
if(userTriggered){ // if the entered to add the task, then go to a new add automatically
311
userTriggered = false;
312
ntTitle.focus.defer(100, ntTitle);
322
'view-all' : function(){
323
taskStore.applyFilter('all');
324
grid.setTitle('All Tasks', 'icon-show-all');
327
'view-active' : function(){
328
taskStore.applyFilter(false);
329
grid.setTitle('Active Tasks', 'icon-show-active');
332
'view-complete' : function(){
333
taskStore.applyFilter(true);
334
grid.setTitle('Completed Tasks', 'icon-show-complete');
337
'action-new' : function(){
341
'action-complete' : function(){
342
selections.each(function(s){
343
s.set('completed', true);
345
taskStore.applyFilter();
348
'action-active' : function(){
349
selections.each(function(s){
350
s.set('completed', false);
352
taskStore.applyFilter();
355
'action-delete' : function(){
356
Ext.Msg.confirm('Confirm', 'Are you sure you want to delete the selected task(s)?',
359
selections.each(function(s){
366
'group-date' : function(){
367
taskStore.groupBy('dueDate');
370
'group-cat' : function(){
371
taskStore.groupBy('category');
374
'no-group' : function(){
375
taskStore.clearGrouping();
379
function doAction(e, t){
385
// generates a renderer function to be used for textual date groups
387
// create the cache of ranges to be reused
388
var today = new Date().clearTime(true);
389
var year = today.getFullYear();
390
var todayTime = today.getTime();
391
var yesterday = today.add('d', -1).getTime();
392
var tomorrow = today.add('d', 1).getTime();
393
var weekDays = today.add('d', 6).getTime();
394
var lastWeekDays = today.add('d', -6).getTime();
396
return function(date){
400
var notime = date.clearTime(true).getTime();
402
if (notime == todayTime) {
405
if(notime > todayTime){
406
if (notime == tomorrow) {
409
if (notime <= weekDays) {
410
return date.format('l');
413
if(notime == yesterday) {
416
if(notime >= lastWeekDays) {
417
return 'Last ' + date.format('l');
420
return date.getFullYear() == year ? date.format('D m/d') : date.format('D m/d/Y');
425
/* This is used to laod some demo tasks if the task database is empty */
426
function loadDemoTasks(store){
428
// hardcoded demo tasks
429
store.addTask({taskId: Task.nextId(), title:'Start documentation of Ext 2.0', category:'Ext', description:'', dueDate: s.add('d', 21), completed: false});
430
store.addTask({taskId: Task.nextId(), title:'Release Ext 1.l Beta 2', category:'Ext', description:'', dueDate:s.add('d', 2), completed: false});
431
store.addTask({taskId: Task.nextId(), title:'Take wife to see movie', category:'Family', description:'', dueDate:s.add('d', 2), completed: false});
432
store.addTask({taskId: Task.nextId(), title:'Finish task list demo app', category:'Ext', description:'', dueDate:s.add('d', 2), completed: false});
433
store.addTask({taskId: Task.nextId(), title:'Do something other than work', category:'Family', description:'', dueDate:s.add('d', -1), completed: false});
434
store.addTask({taskId: Task.nextId(), title:'Go to the grocery store', category:'Family', description:'', dueDate:s.add('d', -1), completed: true});
435
store.addTask({taskId: Task.nextId(), title:'Reboot my computer', category:'Misc', description:'', dueDate:s, completed: false});
436
store.addTask({taskId: Task.nextId(), title:'Respond to emails', category:'Ext', description:'', dueDate:s, completed: true});