2 * Ext JS Library 2.2.1
\r
3 * Copyright(c) 2006-2009, Ext JS, LLC.
\r
4 * licensing@extjs.com
\r
6 * http://extjs.com/license
\r
9 Ext.onReady(function(){
\r
10 Ext.QuickTips.init();
\r
13 // turn off default shadows which look funky in air
\r
14 xg.GridEditor.prototype.shadow = false;
\r
16 var conn = Ext.data.SqlDB.getInstance();
\r
17 conn.open('tasks.db');
\r
19 // the main grid store
\r
20 var taskStore = new TaskStore(conn);
\r
22 // Category store shared by category combos
\r
23 var catStore = new CategoryStore();
\r
26 callback: function(){
\r
28 if(taskStore.getCount() < 1){
\r
29 Ext.Msg.confirm('Create Tasks?', 'Your database is currently empty. Would you like to insert some demo data?',
\r
32 loadDemoTasks(taskStore);
\r
34 catStore.init(taskStore);
\r
37 catStore.init(taskStore);
\r
42 // custom event to notify when a new category is available
\r
43 taskStore.on('newcategory', catStore.addCategory, catStore);
\r
45 // set of event handlers shared by combos to allow them to share
\r
46 // the same local store
\r
49 this.bindStore(catStore);
\r
52 catStore.purgeListeners();
\r
56 var completeColumn = new CompleteColumn();
\r
58 // custom template for the grid header
\r
59 var headerTpl = new Ext.Template(
\r
60 '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
\r
61 '<thead><tr class="x-grid3-hd-row">{cells}</tr></thead>',
\r
62 '<tbody><tr class="new-task-row">',
\r
63 '<td><div id="new-task-icon"></div></td>',
\r
64 '<td><div class="x-small-editor" id="new-task-title"></div></td>',
\r
65 '<td><div class="x-small-editor" id="new-task-cat"></div></td>',
\r
66 '<td><div class="x-small-editor" id="new-task-due"></div></td>',
\r
71 var selections = new Ext.grid.RowSelectionModel();
\r
73 // The main grid in all it's configuration option glory
\r
74 var grid = new xg.EditorGridPanel({
\r
78 clicksToEdit: 'auto',
\r
79 enableColumnHide:false,
\r
80 enableColumnMove:false,
\r
83 iconCls:'icon-show-all',
\r
86 plugins: completeColumn,
\r
96 editor: new Ext.form.TextField({
\r
101 header: "Category",
\r
104 dataIndex: 'category',
\r
105 editor: new Ext.form.ComboBox({
\r
106 displayField: 'text',
\r
107 triggerAction: 'all',
\r
109 selectOnFocus:true,
\r
110 listClass:'x-combo-list-small',
\r
111 listeners: comboEvents
\r
115 header: "Due Date",
\r
118 renderer: Ext.util.Format.dateRenderer('D m/d/Y'),
\r
119 dataIndex: 'dueDate',
\r
120 groupRenderer: textDate(),
\r
122 editor: new Ext.form.DateField({
\r
128 view: new Ext.grid.GroupingView({
\r
131 emptyText: 'No Tasks to display',
\r
137 getRowClass : function(r){
\r
140 return 'task-completed';
\r
142 if(d.dueDate && d.dueDate.getTime() < new Date().clearTime().getTime()){
\r
143 return 'task-overdue';
\r
150 var viewPanel = new Ext.Panel({
\r
154 contentEl:'task-views',
\r
155 titleCollapse: true
\r
158 var taskActions = new Ext.Panel({
\r
160 title: 'Task Actions',
\r
162 contentEl:'task-actions',
\r
163 titleCollapse: true
\r
166 var groupActions = new Ext.Panel({
\r
168 title: 'Task Grouping',
\r
170 contentEl:'task-grouping',
\r
171 titleCollapse: true
\r
174 var actionPanel = new Ext.Panel({
\r
179 collapseMode: 'mini',
\r
184 items: [taskActions, viewPanel, groupActions]
\r
187 if(Ext.isAir){ // create AIR window
\r
188 var win = new Ext.air.MainWindow({
\r
190 items: [actionPanel, grid],
\r
191 title: 'Simple Tasks',
\r
192 iconCls: 'icon-show-all'
\r
195 var viewport = new Ext.Viewport({
\r
197 items: [actionPanel, grid]
\r
201 var ab = actionPanel.body;
\r
202 ab.on('mousedown', doAction, null, {delegate:'a'});
\r
203 ab.on('click', Ext.emptyFn, null, {delegate:'a', preventDefault:true});
\r
205 grid.on('resize', syncFields);
\r
206 grid.on('columnresize', syncFields);
\r
208 grid.on('afteredit', function(e){
\r
209 if(e.field == 'category'){
\r
210 catStore.addCategory(e.value);
\r
212 if(e.field == taskStore.getGroupState()){
\r
213 taskStore.applyGrouping();
\r
218 grid.on('keydown', function(e){
\r
219 if(e.getKey() == e.DELETE && !grid.editing){
\r
220 actions['action-delete']();
\r
224 selections.on('selectionchange', function(sm){
\r
225 var bd = taskActions.body, c = sm.getCount();
\r
226 bd.select('li:not(#new-task)').setDisplayed(c > 0);
\r
227 bd.select('span.s').setDisplayed(c > 1);
\r
230 // The fields in the grid's header
\r
231 var ntTitle = new Ext.form.TextField({
\r
232 renderTo: 'new-task-title',
\r
233 emptyText: 'Add a task...'
\r
236 var ntCat = new Ext.form.ComboBox({
\r
237 renderTo: 'new-task-cat',
\r
239 displayField: 'text',
\r
240 triggerAction: 'all',
\r
242 selectOnFocus:true,
\r
243 listClass:'x-combo-list-small',
\r
244 listeners: comboEvents
\r
247 var ntDue = new Ext.form.DateField({
\r
248 renderTo: 'new-task-due',
\r
254 // syncs the header fields' widths with the grid column widths
\r
255 function syncFields(){
\r
256 var cm = grid.getColumnModel();
\r
257 ntTitle.setSize(cm.getColumnWidth(1)-2);
\r
258 ntCat.setSize(cm.getColumnWidth(2)-4);
\r
259 ntDue.setSize(cm.getColumnWidth(3)-4);
\r
263 var editing = false, focused = false, userTriggered = false;
\r
272 specialkey: function(f, e){
\r
273 if(e.getKey()==e.ENTER){
\r
274 userTriggered = true;
\r
283 ntTitle.on(handlers);
\r
284 ntCat.on(handlers);
\r
285 ntDue.on(handlers);
\r
287 ntTitle.on('focus', function(){
\r
297 // when a field in the add bar is blurred, this determines
\r
298 // whether a new task should be created
\r
300 if(editing && !focused){
\r
301 var title = ntTitle.getValue();
\r
302 if(!Ext.isEmpty(title)){
\r
303 taskStore.addTask({
\r
304 taskId: Task.nextId(),
\r
306 dueDate: ntDue.getValue()||'',
\r
307 description: '', // ???
\r
308 category: ntCat.getValue(),
\r
311 ntTitle.setValue('');
\r
312 if(userTriggered){ // if the entered to add the task, then go to a new add automatically
\r
313 userTriggered = false;
\r
314 ntTitle.focus.defer(100, ntTitle);
\r
324 'view-all' : function(){
\r
325 taskStore.applyFilter('all');
\r
326 grid.setTitle('All Tasks', 'icon-show-all');
\r
329 'view-active' : function(){
\r
330 taskStore.applyFilter(false);
\r
331 grid.setTitle('Active Tasks', 'icon-show-active');
\r
334 'view-complete' : function(){
\r
335 taskStore.applyFilter(true);
\r
336 grid.setTitle('Completed Tasks', 'icon-show-complete');
\r
339 'action-new' : function(){
\r
343 'action-complete' : function(){
\r
344 selections.each(function(s){
\r
345 s.set('completed', true);
\r
347 taskStore.applyFilter();
\r
350 'action-active' : function(){
\r
351 selections.each(function(s){
\r
352 s.set('completed', false);
\r
354 taskStore.applyFilter();
\r
357 'action-delete' : function(){
\r
358 Ext.Msg.confirm('Confirm', 'Are you sure you want to delete the selected task(s)?',
\r
361 selections.each(function(s){
\r
362 taskStore.remove(s);
\r
368 'group-date' : function(){
\r
369 taskStore.groupBy('dueDate');
\r
372 'group-cat' : function(){
\r
373 taskStore.groupBy('category');
\r
376 'no-group' : function(){
\r
377 taskStore.clearGrouping();
\r
381 function doAction(e, t){
\r
387 // generates a renderer function to be used for textual date groups
\r
388 function textDate(){
\r
389 // create the cache of ranges to be reused
\r
390 var today = new Date().clearTime(true);
\r
391 var year = today.getFullYear();
\r
392 var todayTime = today.getTime();
\r
393 var yesterday = today.add('d', -1).getTime();
\r
394 var tomorrow = today.add('d', 1).getTime();
\r
395 var weekDays = today.add('d', 6).getTime();
\r
396 var lastWeekDays = today.add('d', -6).getTime();
\r
398 return function(date){
\r
400 return '(No Date)';
\r
402 var notime = date.clearTime(true).getTime();
\r
404 if (notime == todayTime) {
\r
407 if(notime > todayTime){
\r
408 if (notime == tomorrow) {
\r
411 if (notime <= weekDays) {
\r
412 return date.format('l');
\r
415 if(notime == yesterday) {
\r
416 return 'Yesterday';
\r
418 if(notime >= lastWeekDays) {
\r
419 return 'Last ' + date.format('l');
\r
422 return date.getFullYear() == year ? date.format('D m/d') : date.format('D m/d/Y');
\r
427 /* This is used to laod some demo tasks if the task database is empty */
\r
428 function loadDemoTasks(store){
\r
429 var s = new Date();
\r
430 // hardcoded demo tasks
\r
431 store.addTask({taskId: Task.nextId(), title:'Start documentation of Ext 2.0', category:'Ext', description:'', dueDate: s.add('d', 21), completed: false});
\r
432 store.addTask({taskId: Task.nextId(), title:'Release Ext 1.l Beta 2', category:'Ext', description:'', dueDate:s.add('d', 2), completed: false});
\r
433 store.addTask({taskId: Task.nextId(), title:'Take wife to see movie', category:'Family', description:'', dueDate:s.add('d', 2), completed: false});
\r
434 store.addTask({taskId: Task.nextId(), title:'Finish task list demo app', category:'Ext', description:'', dueDate:s.add('d', 2), completed: false});
\r
435 store.addTask({taskId: Task.nextId(), title:'Do something other than work', category:'Family', description:'', dueDate:s.add('d', -1), completed: false});
\r
436 store.addTask({taskId: Task.nextId(), title:'Go to the grocery store', category:'Family', description:'', dueDate:s.add('d', -1), completed: true});
\r
437 store.addTask({taskId: Task.nextId(), title:'Reboot my computer', category:'Misc', description:'', dueDate:s, completed: false});
\r
438 store.addTask({taskId: Task.nextId(), title:'Respond to emails', category:'Ext', description:'', dueDate:s, completed: true});
\r