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