--- /dev/null
+/*!
+ * Ext JS Library 3.3.0
+ * Copyright(c) 2006-2010 Ext JS, Inc.
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+/*\r
+ * Calendar sample code originally written by Brian Moeskau (brian@ext-calendar.com)\r
+ * See additional calendar examples at http://ext-calendar.com\r
+ */\r
+App = function() {\r
+ return {\r
+ init : function() {\r
+ \r
+ Ext.BLANK_IMAGE_URL = 'http://extjs.cachefly.net/ext-3.1.0/resources/images/default/s.gif';\r
+\r
+ // This is an example calendar store that enables the events to have\r
+ // different colors based on CalendarId. This is not a fully-implmented\r
+ // multi-calendar implementation, which is beyond the scope of this sample app\r
+ this.calendarStore = new Ext.data.JsonStore({\r
+ storeId: 'calendarStore',\r
+ root: 'calendars',\r
+ idProperty: 'id',\r
+ data: calendarList, // defined in calendar-list.js\r
+ proxy: new Ext.data.MemoryProxy(),\r
+ autoLoad: true,\r
+ fields: [\r
+ {name:'CalendarId', mapping: 'id', type: 'int'},\r
+ {name:'Title', mapping: 'title', type: 'string'}\r
+ ],\r
+ sortInfo: {\r
+ field: 'CalendarId',\r
+ direction: 'ASC'\r
+ }\r
+ });\r
+\r
+ // A sample event store that loads static JSON from a local file. Obviously a real\r
+ // implementation would likely be loading remote data via an HttpProxy, but the\r
+ // underlying store functionality is the same. Note that if you would like to \r
+ // provide custom data mappings for events, see EventRecord.js.\r
+ this.eventStore = new Ext.data.JsonStore({\r
+ id: 'eventStore',\r
+ root: 'evts',\r
+ data: eventList, // defined in event-list.js\r
+ proxy: new Ext.data.MemoryProxy(),\r
+ fields: Ext.calendar.EventRecord.prototype.fields.getRange(),\r
+ sortInfo: {\r
+ field: 'StartDate',\r
+ direction: 'ASC'\r
+ }\r
+ });\r
+ \r
+ // This is the app UI layout code. All of the calendar views are subcomponents of\r
+ // CalendarPanel, but the app title bar and sidebar/navigation calendar are separate\r
+ // pieces that are composed in app-specific layout code since they could be ommitted\r
+ // or placed elsewhere within the application.\r
+ new Ext.Viewport({\r
+ layout: 'border',\r
+ renderTo: 'calendar-ct',\r
+ items: [{\r
+ id: 'app-header',\r
+ region: 'north',\r
+ height: 35,\r
+ border: false,\r
+ contentEl: 'app-header-content'\r
+ },{\r
+ id: 'app-center',\r
+ title: '...', // will be updated to view date range\r
+ region: 'center',\r
+ layout: 'border',\r
+ items: [{\r
+ id:'app-west',\r
+ region: 'west',\r
+ width: 176,\r
+ border: false,\r
+ items: [{\r
+ xtype: 'datepicker',\r
+ id: 'app-nav-picker',\r
+ cls: 'ext-cal-nav-picker',\r
+ listeners: {\r
+ 'select': {\r
+ fn: function(dp, dt){\r
+ App.calendarPanel.setStartDate(dt);\r
+ },\r
+ scope: this\r
+ }\r
+ }\r
+ }]\r
+ },{\r
+ xtype: 'calendarpanel',\r
+ eventStore: this.eventStore,\r
+ calendarStore: this.calendarStore,\r
+ border: false,\r
+ id:'app-calendar',\r
+ region: 'center',\r
+ activeItem: 2, // month view\r
+ \r
+ // CalendarPanel supports view-specific configs that are passed through to the \r
+ // underlying views to make configuration possible without explicitly having to \r
+ // create those views at this level:\r
+ monthViewCfg: {\r
+ showHeader: true,\r
+ showWeekLinks: true,\r
+ showWeekNumbers: true\r
+ },\r
+ \r
+ // Some optional CalendarPanel configs to experiment with:\r
+ //showDayView: false,\r
+ //showWeekView: false,\r
+ //showMonthView: false,\r
+ //showNavBar: false,\r
+ //showTodayText: false,\r
+ //showTime: false,\r
+ //title: 'My Calendar', // the header of the calendar, could be a subtitle for the app\r
+ \r
+ // Once this component inits it will set a reference to itself as an application\r
+ // member property for easy reference in other functions within App.\r
+ initComponent: function() {\r
+ App.calendarPanel = this;\r
+ this.constructor.prototype.initComponent.apply(this, arguments);\r
+ },\r
+ \r
+ listeners: {\r
+ 'eventclick': {\r
+ fn: function(vw, rec, el){\r
+ this.showEditWindow(rec, el);\r
+ this.clearMsg();\r
+ },\r
+ scope: this\r
+ },\r
+ 'eventover': function(vw, rec, el){\r
+ //console.log('Entered evt rec='+rec.data.Title+', view='+ vw.id +', el='+el.id);\r
+ },\r
+ 'eventout': function(vw, rec, el){\r
+ //console.log('Leaving evt rec='+rec.data.Title+', view='+ vw.id +', el='+el.id);\r
+ },\r
+ 'eventadd': {\r
+ fn: function(cp, rec){\r
+ this.showMsg('Event '+ rec.data.Title +' was added');\r
+ },\r
+ scope: this\r
+ },\r
+ 'eventupdate': {\r
+ fn: function(cp, rec){\r
+ this.showMsg('Event '+ rec.data.Title +' was updated');\r
+ },\r
+ scope: this\r
+ },\r
+ 'eventdelete': {\r
+ fn: function(cp, rec){\r
+ this.showMsg('Event '+ rec.data.Title +' was deleted');\r
+ },\r
+ scope: this\r
+ },\r
+ 'eventcancel': {\r
+ fn: function(cp, rec){\r
+ // edit canceled\r
+ },\r
+ scope: this\r
+ },\r
+ 'viewchange': {\r
+ fn: function(p, vw, dateInfo){\r
+ if(this.editWin){\r
+ this.editWin.hide();\r
+ };\r
+ if(dateInfo !== null){\r
+ // will be null when switching to the event edit form so ignore\r
+ Ext.getCmp('app-nav-picker').setValue(dateInfo.activeDate);\r
+ this.updateTitle(dateInfo.viewStart, dateInfo.viewEnd);\r
+ }\r
+ },\r
+ scope: this\r
+ },\r
+ 'dayclick': {\r
+ fn: function(vw, dt, ad, el){\r
+ this.showEditWindow({\r
+ StartDate: dt,\r
+ IsAllDay: ad\r
+ }, el);\r
+ this.clearMsg();\r
+ },\r
+ scope: this\r
+ },\r
+ 'rangeselect': {\r
+ fn: function(win, dates, onComplete){\r
+ this.showEditWindow(dates);\r
+ this.editWin.on('hide', onComplete, this, {single:true});\r
+ this.clearMsg();\r
+ },\r
+ scope: this\r
+ },\r
+ 'eventmove': {\r
+ fn: function(vw, rec){\r
+ rec.commit();\r
+ var time = rec.data.IsAllDay ? '' : ' \\a\\t g:i a';\r
+ this.showMsg('Event '+ rec.data.Title +' was moved to '+rec.data.StartDate.format('F jS'+time));\r
+ },\r
+ scope: this\r
+ },\r
+ 'eventresize': {\r
+ fn: function(vw, rec){\r
+ rec.commit();\r
+ this.showMsg('Event '+ rec.data.Title +' was updated');\r
+ },\r
+ scope: this\r
+ },\r
+ 'eventdelete': {\r
+ fn: function(win, rec){\r
+ this.eventStore.remove(rec);\r
+ this.showMsg('Event '+ rec.data.Title +' was deleted');\r
+ },\r
+ scope: this\r
+ },\r
+ 'initdrag': {\r
+ fn: function(vw){\r
+ if(this.editWin && this.editWin.isVisible()){\r
+ this.editWin.hide();\r
+ }\r
+ },\r
+ scope: this\r
+ }\r
+ }\r
+ }]\r
+ }]\r
+ });\r
+ },\r
+ \r
+ // The edit popup window is not part of the CalendarPanel itself -- it is a separate component.\r
+ // This makes it very easy to swap it out with a different type of window or custom view, or omit\r
+ // it altogether. Because of this, it's up to the application code to tie the pieces together.\r
+ // Note that this function is called from various event handlers in the CalendarPanel above.\r
+ showEditWindow : function(rec, animateTarget){\r
+ if(!this.editWin){\r
+ this.editWin = new Ext.calendar.EventEditWindow({\r
+ calendarStore: this.calendarStore,\r
+ listeners: {\r
+ 'eventadd': {\r
+ fn: function(win, rec){\r
+ win.hide();\r
+ rec.data.IsNew = false;\r
+ this.eventStore.add(rec);\r
+ this.showMsg('Event '+ rec.data.Title +' was added');\r
+ },\r
+ scope: this\r
+ },\r
+ 'eventupdate': {\r
+ fn: function(win, rec){\r
+ win.hide();\r
+ rec.commit();\r
+ this.showMsg('Event '+ rec.data.Title +' was updated');\r
+ },\r
+ scope: this\r
+ },\r
+ 'eventdelete': {\r
+ fn: function(win, rec){\r
+ this.eventStore.remove(rec);\r
+ win.hide();\r
+ this.showMsg('Event '+ rec.data.Title +' was deleted');\r
+ },\r
+ scope: this\r
+ },\r
+ 'editdetails': {\r
+ fn: function(win, rec){\r
+ win.hide();\r
+ App.calendarPanel.showEditForm(rec);\r
+ }\r
+ }\r
+ }\r
+ });\r
+ }\r
+ this.editWin.show(rec, animateTarget);\r
+ },\r
+ \r
+ // The CalendarPanel itself supports the standard Panel title config, but that title\r
+ // only spans the calendar views. For a title that spans the entire width of the app\r
+ // we added a title to the layout's outer center region that is app-specific. This code\r
+ // updates that outer title based on the currently-selected view range anytime the view changes.\r
+ updateTitle: function(startDt, endDt){\r
+ var p = Ext.getCmp('app-center');\r
+ \r
+ if(startDt.clearTime().getTime() == endDt.clearTime().getTime()){\r
+ p.setTitle(startDt.format('F j, Y'));\r
+ }\r
+ else if(startDt.getFullYear() == endDt.getFullYear()){\r
+ if(startDt.getMonth() == endDt.getMonth()){\r
+ p.setTitle(startDt.format('F j') + ' - ' + endDt.format('j, Y'));\r
+ }\r
+ else{\r
+ p.setTitle(startDt.format('F j') + ' - ' + endDt.format('F j, Y'));\r
+ }\r
+ }\r
+ else{\r
+ p.setTitle(startDt.format('F j, Y') + ' - ' + endDt.format('F j, Y'));\r
+ }\r
+ },\r
+ \r
+ // This is an application-specific way to communicate CalendarPanel event messages back to the user.\r
+ // This could be replaced with a function to do "toast" style messages, growl messages, etc. This will\r
+ // vary based on application requirements, which is why it's not baked into the CalendarPanel.\r
+ showMsg: function(msg){\r
+ Ext.fly('app-msg').update(msg).removeClass('x-hidden');\r
+ },\r
+ \r
+ clearMsg: function(){\r
+ Ext.fly('app-msg').update('').addClass('x-hidden');\r
+ }\r
+ }\r
+}();\r
+\r
+Ext.onReady(App.init, App);\r