3 * Copyright(c) 2006-2010 Sencha Inc.
5 * http://www.sencha.com/license
8 * @class Ext.calendar.CalendarPanel
10 * <p>This is the default container for Ext calendar views. It supports day, week and month views as well
11 * as a built-in event edit form. The only requirement for displaying a calendar is passing in a valid
12 * {@link #calendarStore} config containing records of type {@link Ext.calendar.EventRecord EventRecord}. In order
13 * to make the calendar interactive (enable editing, drag/drop, etc.) you can handle any of the various
14 * events fired by the underlying views and exposed through the CalendarPanel.</p>
15 * {@link #layoutConfig} option if needed.</p>
17 * @param {Object} config The config object
18 * @xtype calendarpanel
20 Ext.calendar.CalendarPanel = Ext.extend(Ext.Panel, {
22 * @cfg {Boolean} showDayView
23 * True to include the day view (and toolbar button), false to hide them (defaults to true).
27 * @cfg {Boolean} showWeekView
28 * True to include the week view (and toolbar button), false to hide them (defaults to true).
32 * @cfg {Boolean} showMonthView
33 * True to include the month view (and toolbar button), false to hide them (defaults to true).
34 * If the day and week views are both hidden, the month view will show by default even if
35 * this config is false.
39 * @cfg {Boolean} showNavBar
40 * True to display the calendar navigation toolbar, false to hide it (defaults to true). Note that
41 * if you hide the default navigation toolbar you'll have to provide an alternate means of navigating the calendar.
45 * @cfg {String} todayText
46 * Alternate text to use for the 'Today' nav bar button.
50 * @cfg {Boolean} showTodayText
51 * True to show the value of {@link #todayText} instead of today's date in the calendar's current day box,
52 * false to display the day number(defaults to true).
56 * @cfg {Boolean} showTime
57 * True to display the current time next to the date in the calendar's current day box, false to not show it
62 * @cfg {String} dayText
63 * Alternate text to use for the 'Day' nav bar button.
67 * @cfg {String} weekText
68 * Alternate text to use for the 'Week' nav bar button.
72 * @cfg {String} monthText
73 * Alternate text to use for the 'Month' nav bar button.
79 layoutOnCardChange: true,
84 startDate: new Date(),
87 initComponent: function() {
89 cls: 'ext-cal-toolbar',
91 buttonAlign: 'center',
93 id: this.id + '-tb-prev',
94 handler: this.onPrevClick,
96 iconCls: 'x-tbar-page-prev'
102 if (this.showDayView) {
103 this.tbar.items.push({
104 id: this.id + '-tb-day',
106 handler: this.onDayClick,
108 toggleGroup: 'tb-views'
112 if (this.showWeekView) {
113 this.tbar.items.push({
114 id: this.id + '-tb-week',
116 handler: this.onWeekClick,
118 toggleGroup: 'tb-views'
122 if (this.showMonthView || this.viewCount == 0) {
123 this.tbar.items.push({
124 id: this.id + '-tb-month',
125 text: this.monthText,
126 handler: this.onMonthClick,
128 toggleGroup: 'tb-views'
131 this.showMonthView = true;
133 this.tbar.items.push({
134 id: this.id + '-tb-next',
135 handler: this.onNextClick,
137 iconCls: 'x-tbar-page-next'
139 this.tbar.items.push('->');
141 var idx = this.viewCount - 1;
142 this.activeItem = this.activeItem === undefined ? idx: (this.activeItem > idx ? idx: this.activeItem);
144 if (this.showNavBar === false) {
146 this.addClass('x-calendar-nonav');
149 Ext.calendar.CalendarPanel.superclass.initComponent.call(this);
154 * Fires after a new event is added to the underlying store
155 * @param {Ext.calendar.CalendarPanel} this
156 * @param {Ext.calendar.EventRecord} rec The new {@link Ext.calendar.EventRecord record} that was added
161 * Fires after an existing event is updated
162 * @param {Ext.calendar.CalendarPanel} this
163 * @param {Ext.calendar.EventRecord} rec The new {@link Ext.calendar.EventRecord record} that was updated
168 * Fires after an event is removed from the underlying store
169 * @param {Ext.calendar.CalendarPanel} this
170 * @param {Ext.calendar.EventRecord} rec The new {@link Ext.calendar.EventRecord record} that was removed
175 * Fires after an event add/edit operation is canceled by the user and no store update took place
176 * @param {Ext.calendar.CalendarPanel} this
177 * @param {Ext.calendar.EventRecord} rec The new {@link Ext.calendar.EventRecord record} that was canceled
182 * Fires after a different calendar view is activated (but not when the event edit form is activated)
183 * @param {Ext.calendar.CalendarPanel} this
184 * @param {Ext.CalendarView} view The view being activated (any valid {@link Ext.calendar.CalendarView CalendarView} subclass)
185 * @param {Object} info Extra information about the newly activated view. This is a plain object
186 * with following properties:<div class="mdetail-params"><ul>
187 * <li><b><code>activeDate</code></b> : <div class="sub-desc">The currently-selected date</div></li>
188 * <li><b><code>viewStart</code></b> : <div class="sub-desc">The first date in the new view range</div></li>
189 * <li><b><code>viewEnd</code></b> : <div class="sub-desc">The last date in the new view range</div></li>
195 // NOTE: CalendarPanel also relays the following events from contained views as if they originated from this:
198 * @event eventsrendered
199 * Fires after events are finished rendering in the view
200 * @param {Ext.calendar.CalendarPanel} this
204 * Fires after the user clicks on an event element
205 * @param {Ext.calendar.CalendarPanel} this
206 * @param {Ext.calendar.EventRecord} rec The {@link Ext.calendar.EventRecord record} for the event that was clicked on
207 * @param {HTMLNode} el The DOM node that was clicked on
211 * Fires anytime the mouse is over an event element
212 * @param {Ext.calendar.CalendarPanel} this
213 * @param {Ext.calendar.EventRecord} rec The {@link Ext.calendar.EventRecord record} for the event that the cursor is over
214 * @param {HTMLNode} el The DOM node that is being moused over
218 * Fires anytime the mouse exits an event element
219 * @param {Ext.calendar.CalendarPanel} this
220 * @param {Ext.calendar.EventRecord} rec The {@link Ext.calendar.EventRecord record} for the event that the cursor exited
221 * @param {HTMLNode} el The DOM node that was exited
225 * Fires after the start date of the view changes
226 * @param {Ext.calendar.CalendarPanel} this
227 * @param {Date} startDate The start date of the view (as explained in {@link #getStartDate}
228 * @param {Date} viewStart The first displayed date in the view
229 * @param {Date} viewEnd The last displayed date in the view
233 * Fires after the user drags on the calendar to select a range of dates/times in which to create an event
234 * @param {Ext.calendar.CalendarPanel} this
235 * @param {Object} dates An object containing the start (StartDate property) and end (EndDate property) dates selected
236 * @param {Function} callback A callback function that MUST be called after the event handling is complete so that
237 * the view is properly cleaned up (shim elements are persisted in the view while the user is prompted to handle the
238 * range selection). The callback is already created in the proper scope, so it simply needs to be executed as a standard
239 * function call (e.g., callback()).
243 * Fires after an event element is dragged by the user and dropped in a new position
244 * @param {Ext.calendar.CalendarPanel} this
245 * @param {Ext.calendar.EventRecord} rec The {@link Ext.calendar.EventRecord record} for the event that was moved with
246 * updated start and end dates
250 * Fires when a drag operation is initiated in the view
251 * @param {Ext.calendar.CalendarPanel} this
255 * Fires after the user drags the resize handle of an event to resize it
256 * @param {Ext.calendar.CalendarPanel} this
257 * @param {Ext.calendar.EventRecord} rec The {@link Ext.calendar.EventRecord record} for the event that was resized
258 * containing the updated start and end dates
262 * Fires after the user clicks within a day/week view container and not on an event element
263 * @param {Ext.calendar.CalendarPanel} this
264 * @param {Date} dt The date/time that was clicked on
265 * @param {Boolean} allday True if the day clicked on represents an all-day box, else false.
266 * @param {Ext.Element} el The Element that was clicked on
270 this.layout = 'card';
271 // do not allow override
272 if (this.showDayView) {
273 var day = Ext.apply({
276 showToday: this.showToday,
277 showTodayText: this.showTodayText,
278 showTime: this.showTime
282 day.id = this.id + '-day';
283 day.store = day.store || this.eventStore;
284 this.initEventRelay(day);
287 if (this.showWeekView) {
288 var wk = Ext.applyIf({
290 title: this.weekText,
291 showToday: this.showToday,
292 showTodayText: this.showTodayText,
293 showTime: this.showTime
297 wk.id = this.id + '-week';
298 wk.store = wk.store || this.eventStore;
299 this.initEventRelay(wk);
302 if (this.showMonthView) {
303 var month = Ext.applyIf({
305 title: this.monthText,
306 showToday: this.showToday,
307 showTodayText: this.showTodayText,
308 showTime: this.showTime,
311 fn: function(vw, dt) {
320 month.id = this.id + '-month';
321 month.store = month.store || this.eventStore;
322 this.initEventRelay(month);
326 this.add(Ext.applyIf({
327 xtype: 'eventeditform',
328 id: this.id + '-edit',
329 calendarStore: this.calendarStore,
337 fn: this.onEventUpdate
341 fn: this.onEventDelete
345 fn: this.onEventCancel
353 initEventRelay: function(cfg) {
354 cfg.listeners = cfg.listeners || {};
355 cfg.listeners.afterrender = {
357 // relay the view events so that app code only has to handle them in one place
358 this.relayEvents(c, ['eventsrendered', 'eventclick', 'eventover', 'eventout', 'dayclick',
359 'eventmove', 'datechange', 'rangeselect', 'eventdelete', 'eventresize', 'initdrag']);
367 afterRender: function() {
368 Ext.calendar.CalendarPanel.superclass.afterRender.call(this);
369 this.fireViewChange();
373 onLayout: function() {
374 Ext.calendar.CalendarPanel.superclass.onLayout.call(this);
375 if (!this.navInitComplete) {
376 this.updateNavState();
377 this.navInitComplete = true;
382 onEventAdd: function(form, rec) {
383 rec.data[Ext.calendar.EventMappings.IsNew.name] = false;
384 this.eventStore.add(rec);
386 this.fireEvent('eventadd', this, rec);
390 onEventUpdate: function(form, rec) {
393 this.fireEvent('eventupdate', this, rec);
397 onEventDelete: function(form, rec) {
398 this.eventStore.remove(rec);
400 this.fireEvent('eventdelete', this, rec);
404 onEventCancel: function(form, rec) {
406 this.fireEvent('eventcancel', this, rec);
410 * Shows the built-in event edit form for the passed in event record. This method automatically
411 * hides the calendar views and navigation toolbar. To return to the calendar, call {@link #hideEditForm}.
412 * @param {Ext.calendar.EventRecord} record The event record to edit
413 * @return {Ext.calendar.CalendarPanel} this
415 showEditForm: function(rec) {
416 this.preEditView = this.layout.activeItem.id;
417 this.setActiveView(this.id + '-edit');
418 this.layout.activeItem.loadRecord(rec);
423 * Hides the built-in event edit form and returns to the previous calendar view. If the edit form is
424 * not currently visible this method has no effect.
425 * @return {Ext.calendar.CalendarPanel} this
427 hideEditForm: function() {
428 if (this.preEditView) {
429 this.setActiveView(this.preEditView);
430 delete this.preEditView;
436 setActiveView: function(id) {
440 if (id == this.id + '-edit') {
441 this.getTopToolbar().hide();
445 l.activeItem.refresh();
446 this.getTopToolbar().show();
447 this.updateNavState();
449 this.activeView = l.activeItem;
450 this.fireViewChange();
454 fireViewChange: function() {
456 view = this.layout.activeItem;
458 if (view.getViewBounds) {
459 vb = view.getViewBounds();
461 activeDate: view.getStartDate(),
466 this.fireEvent('viewchange', this, view, info);
470 updateNavState: function() {
471 if (this.showNavBar !== false) {
472 var item = this.layout.activeItem,
473 suffix = item.id.split(this.id + '-')[1];
475 var btn = Ext.getCmp(this.id + '-tb-' + suffix);
481 * Sets the start date for the currently-active calendar view.
484 setStartDate: function(dt) {
485 this.layout.activeItem.setStartDate(dt, true);
486 this.updateNavState();
487 this.fireViewChange();
491 showWeek: function(dt) {
492 this.setActiveView(this.id + '-week');
493 this.setStartDate(dt);
497 onPrevClick: function() {
498 this.startDate = this.layout.activeItem.movePrev();
499 this.updateNavState();
500 this.fireViewChange();
504 onNextClick: function() {
505 this.startDate = this.layout.activeItem.moveNext();
506 this.updateNavState();
507 this.fireViewChange();
511 onDayClick: function() {
512 this.setActiveView(this.id + '-day');
516 onWeekClick: function() {
517 this.setActiveView(this.id + '-week');
521 onMonthClick: function() {
522 this.setActiveView(this.id + '-month');
526 * Return the calendar view that is currently active, which will be a subclass of
527 * {@link Ext.calendar.CalendarView CalendarView}.
528 * @return {Ext.calendar.CalendarView} The active view
530 getActiveView: function() {
531 return this.layout.activeItem;
535 Ext.reg('calendarpanel', Ext.calendar.CalendarPanel);