f702a42e17096e452d20100202d671146516794d
[extjs.git] / examples / calendar / app / test-app.js
1 /*!
2  * Ext JS Library 3.3.0
3  * Copyright(c) 2006-2010 Ext JS, Inc.
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /*\r
8  * Calendar sample code originally written by Brian Moeskau (brian@ext-calendar.com)\r
9  * See additional calendar examples at http://ext-calendar.com\r
10  */\r
11 App = function() {\r
12     return {\r
13         init : function() {\r
14             \r
15             Ext.BLANK_IMAGE_URL = 'http://extjs.cachefly.net/ext-3.1.0/resources/images/default/s.gif';\r
16 \r
17             // This is an example calendar store that enables the events to have\r
18             // different colors based on CalendarId. This is not a fully-implmented\r
19             // multi-calendar implementation, which is beyond the scope of this sample app\r
20             this.calendarStore = new Ext.data.JsonStore({\r
21                 storeId: 'calendarStore',\r
22                 root: 'calendars',\r
23                 idProperty: 'id',\r
24                 data: calendarList, // defined in calendar-list.js\r
25                 proxy: new Ext.data.MemoryProxy(),\r
26                 autoLoad: true,\r
27                 fields: [\r
28                     {name:'CalendarId', mapping: 'id', type: 'int'},\r
29                     {name:'Title', mapping: 'title', type: 'string'}\r
30                 ],\r
31                 sortInfo: {\r
32                     field: 'CalendarId',\r
33                     direction: 'ASC'\r
34                 }\r
35             });\r
36 \r
37             // A sample event store that loads static JSON from a local file. Obviously a real\r
38             // implementation would likely be loading remote data via an HttpProxy, but the\r
39             // underlying store functionality is the same.  Note that if you would like to \r
40             // provide custom data mappings for events, see EventRecord.js.\r
41                     this.eventStore = new Ext.data.JsonStore({\r
42                         id: 'eventStore',\r
43                         root: 'evts',\r
44                         data: eventList, // defined in event-list.js\r
45                                 proxy: new Ext.data.MemoryProxy(),\r
46                         fields: Ext.calendar.EventRecord.prototype.fields.getRange(),\r
47                         sortInfo: {\r
48                             field: 'StartDate',\r
49                             direction: 'ASC'\r
50                         }\r
51                     });\r
52             \r
53             // This is the app UI layout code.  All of the calendar views are subcomponents of\r
54             // CalendarPanel, but the app title bar and sidebar/navigation calendar are separate\r
55             // pieces that are composed in app-specific layout code since they could be ommitted\r
56             // or placed elsewhere within the application.\r
57             new Ext.Viewport({\r
58                 layout: 'border',\r
59                 renderTo: 'calendar-ct',\r
60                 items: [{\r
61                     id: 'app-header',\r
62                     region: 'north',\r
63                     height: 35,\r
64                     border: false,\r
65                     contentEl: 'app-header-content'\r
66                 },{\r
67                     id: 'app-center',\r
68                     title: '...', // will be updated to view date range\r
69                     region: 'center',\r
70                     layout: 'border',\r
71                     items: [{\r
72                         id:'app-west',\r
73                         region: 'west',\r
74                         width: 176,\r
75                         border: false,\r
76                         items: [{\r
77                             xtype: 'datepicker',\r
78                             id: 'app-nav-picker',\r
79                             cls: 'ext-cal-nav-picker',\r
80                             listeners: {\r
81                                 'select': {\r
82                                     fn: function(dp, dt){\r
83                                         App.calendarPanel.setStartDate(dt);\r
84                                     },\r
85                                     scope: this\r
86                                 }\r
87                             }\r
88                         }]\r
89                     },{\r
90                         xtype: 'calendarpanel',\r
91                         eventStore: this.eventStore,\r
92                         calendarStore: this.calendarStore,\r
93                         border: false,\r
94                         id:'app-calendar',\r
95                         region: 'center',\r
96                         activeItem: 2, // month view\r
97                         \r
98                         // CalendarPanel supports view-specific configs that are passed through to the \r
99                         // underlying views to make configuration possible without explicitly having to \r
100                         // create those views at this level:\r
101                         monthViewCfg: {\r
102                             showHeader: true,\r
103                             showWeekLinks: true,\r
104                             showWeekNumbers: true\r
105                         },\r
106                         \r
107                         // Some optional CalendarPanel configs to experiment with:\r
108                         //showDayView: false,\r
109                         //showWeekView: false,\r
110                         //showMonthView: false,\r
111                         //showNavBar: false,\r
112                         //showTodayText: false,\r
113                         //showTime: false,\r
114                         //title: 'My Calendar', // the header of the calendar, could be a subtitle for the app\r
115                         \r
116                         // Once this component inits it will set a reference to itself as an application\r
117                         // member property for easy reference in other functions within App.\r
118                         initComponent: function() {\r
119                             App.calendarPanel = this;\r
120                             this.constructor.prototype.initComponent.apply(this, arguments);\r
121                         },\r
122                         \r
123                         listeners: {\r
124                             'eventclick': {\r
125                                 fn: function(vw, rec, el){\r
126                                     this.showEditWindow(rec, el);\r
127                                     this.clearMsg();\r
128                                 },\r
129                                 scope: this\r
130                             },\r
131                             'eventover': function(vw, rec, el){\r
132                                 //console.log('Entered evt rec='+rec.data.Title+', view='+ vw.id +', el='+el.id);\r
133                             },\r
134                             'eventout': function(vw, rec, el){\r
135                                 //console.log('Leaving evt rec='+rec.data.Title+', view='+ vw.id +', el='+el.id);\r
136                             },\r
137                             'eventadd': {\r
138                                 fn: function(cp, rec){\r
139                                     this.showMsg('Event '+ rec.data.Title +' was added');\r
140                                 },\r
141                                 scope: this\r
142                             },\r
143                             'eventupdate': {\r
144                                 fn: function(cp, rec){\r
145                                     this.showMsg('Event '+ rec.data.Title +' was updated');\r
146                                 },\r
147                                 scope: this\r
148                             },\r
149                             'eventdelete': {\r
150                                 fn: function(cp, rec){\r
151                                     this.showMsg('Event '+ rec.data.Title +' was deleted');\r
152                                 },\r
153                                 scope: this\r
154                             },\r
155                             'eventcancel': {\r
156                                 fn: function(cp, rec){\r
157                                     // edit canceled\r
158                                 },\r
159                                 scope: this\r
160                             },\r
161                             'viewchange': {\r
162                                 fn: function(p, vw, dateInfo){\r
163                                     if(this.editWin){\r
164                                         this.editWin.hide();\r
165                                     };\r
166                                     if(dateInfo !== null){\r
167                                         // will be null when switching to the event edit form so ignore\r
168                                         Ext.getCmp('app-nav-picker').setValue(dateInfo.activeDate);\r
169                                         this.updateTitle(dateInfo.viewStart, dateInfo.viewEnd);\r
170                                     }\r
171                                 },\r
172                                 scope: this\r
173                             },\r
174                             'dayclick': {\r
175                                 fn: function(vw, dt, ad, el){\r
176                                     this.showEditWindow({\r
177                                         StartDate: dt,\r
178                                         IsAllDay: ad\r
179                                     }, el);\r
180                                     this.clearMsg();\r
181                                 },\r
182                                 scope: this\r
183                             },\r
184                             'rangeselect': {\r
185                                 fn: function(win, dates, onComplete){\r
186                                     this.showEditWindow(dates);\r
187                                     this.editWin.on('hide', onComplete, this, {single:true});\r
188                                     this.clearMsg();\r
189                                 },\r
190                                 scope: this\r
191                             },\r
192                             'eventmove': {\r
193                                 fn: function(vw, rec){\r
194                                     rec.commit();\r
195                                     var time = rec.data.IsAllDay ? '' : ' \\a\\t g:i a';\r
196                                     this.showMsg('Event '+ rec.data.Title +' was moved to '+rec.data.StartDate.format('F jS'+time));\r
197                                 },\r
198                                 scope: this\r
199                             },\r
200                             'eventresize': {\r
201                                 fn: function(vw, rec){\r
202                                     rec.commit();\r
203                                     this.showMsg('Event '+ rec.data.Title +' was updated');\r
204                                 },\r
205                                 scope: this\r
206                             },\r
207                             'eventdelete': {\r
208                                 fn: function(win, rec){\r
209                                     this.eventStore.remove(rec);\r
210                                     this.showMsg('Event '+ rec.data.Title +' was deleted');\r
211                                 },\r
212                                 scope: this\r
213                             },\r
214                             'initdrag': {\r
215                                 fn: function(vw){\r
216                                     if(this.editWin && this.editWin.isVisible()){\r
217                                         this.editWin.hide();\r
218                                     }\r
219                                 },\r
220                                 scope: this\r
221                             }\r
222                         }\r
223                     }]\r
224                 }]\r
225             });\r
226         },\r
227         \r
228         // The edit popup window is not part of the CalendarPanel itself -- it is a separate component.\r
229         // This makes it very easy to swap it out with a different type of window or custom view, or omit\r
230         // it altogether. Because of this, it's up to the application code to tie the pieces together.\r
231         // Note that this function is called from various event handlers in the CalendarPanel above.\r
232                 showEditWindow : function(rec, animateTarget){\r
233                 if(!this.editWin){\r
234                     this.editWin = new Ext.calendar.EventEditWindow({\r
235                     calendarStore: this.calendarStore,\r
236                                         listeners: {\r
237                                                 'eventadd': {\r
238                                                         fn: function(win, rec){\r
239                                                                 win.hide();\r
240                                                                 rec.data.IsNew = false;\r
241                                                                 this.eventStore.add(rec);\r
242                                 this.showMsg('Event '+ rec.data.Title +' was added');\r
243                                                         },\r
244                                                         scope: this\r
245                                                 },\r
246                                                 'eventupdate': {\r
247                                                         fn: function(win, rec){\r
248                                                                 win.hide();\r
249                                                                 rec.commit();\r
250                                 this.showMsg('Event '+ rec.data.Title +' was updated');\r
251                                                         },\r
252                                                         scope: this\r
253                                                 },\r
254                                                 'eventdelete': {\r
255                                                         fn: function(win, rec){\r
256                                                                 this.eventStore.remove(rec);\r
257                                                                 win.hide();\r
258                                 this.showMsg('Event '+ rec.data.Title +' was deleted');\r
259                                                         },\r
260                                                         scope: this\r
261                                                 },\r
262                         'editdetails': {\r
263                             fn: function(win, rec){\r
264                                 win.hide();\r
265                                 App.calendarPanel.showEditForm(rec);\r
266                             }\r
267                         }\r
268                                         }\r
269                 });\r
270                 }\r
271                 this.editWin.show(rec, animateTarget);\r
272                 },\r
273         \r
274         // The CalendarPanel itself supports the standard Panel title config, but that title\r
275         // only spans the calendar views.  For a title that spans the entire width of the app\r
276         // we added a title to the layout's outer center region that is app-specific. This code\r
277         // updates that outer title based on the currently-selected view range anytime the view changes.\r
278         updateTitle: function(startDt, endDt){\r
279             var p = Ext.getCmp('app-center');\r
280             \r
281             if(startDt.clearTime().getTime() == endDt.clearTime().getTime()){\r
282                 p.setTitle(startDt.format('F j, Y'));\r
283             }\r
284             else if(startDt.getFullYear() == endDt.getFullYear()){\r
285                 if(startDt.getMonth() == endDt.getMonth()){\r
286                     p.setTitle(startDt.format('F j') + ' - ' + endDt.format('j, Y'));\r
287                 }\r
288                 else{\r
289                     p.setTitle(startDt.format('F j') + ' - ' + endDt.format('F j, Y'));\r
290                 }\r
291             }\r
292             else{\r
293                 p.setTitle(startDt.format('F j, Y') + ' - ' + endDt.format('F j, Y'));\r
294             }\r
295         },\r
296         \r
297         // This is an application-specific way to communicate CalendarPanel event messages back to the user.\r
298         // This could be replaced with a function to do "toast" style messages, growl messages, etc. This will\r
299         // vary based on application requirements, which is why it's not baked into the CalendarPanel.\r
300         showMsg: function(msg){\r
301             Ext.fly('app-msg').update(msg).removeClass('x-hidden');\r
302         },\r
303         \r
304         clearMsg: function(){\r
305             Ext.fly('app-msg').update('').addClass('x-hidden');\r
306         }\r
307     }\r
308 }();\r
309 \r
310 Ext.onReady(App.init, App);\r