/** * @class Ext.ensible.cal.DayBodyView * @extends Ext.ensible.cal.CalendarView *This is the scrolling container within the day and week views where non-all-day events are displayed. * Normally you should not need to use this class directly -- instead you should use {@link Ext.ensible.cal.DayView DayView} * which aggregates this class and the {@link Ext.ensible.cal.DayHeaderView DayHeaderView} into the single unified view * presented by {@link Ext.ensible.cal.CalendarPanel CalendarPanel}.
* @constructor * @param {Object} config The config object */ Ext.ensible.cal.DayBodyView = Ext.extend(Ext.ensible.cal.CalendarView, { //private dayColumnElIdDelimiter: '-day-col-', hourIncrement: 60, //private initComponent : function(){ Ext.ensible.cal.DayBodyView.superclass.initComponent.call(this); if(this.readOnly === true){ this.enableEventResize = false; } this.incrementsPerHour = this.hourIncrement / this.ddIncrement; this.minEventHeight = this.minEventDisplayMinutes / (this.hourIncrement / this.hourHeight); this.addEvents({ /** * @event beforeeventresize * Fires after the user drags the resize handle of an event to resize it, but before the resize operation is carried out. * This is a cancelable event, so returning false from a handler will cancel the resize operation. * @param {Ext.ensible.cal.DayBodyView} this * @param {Ext.ensible.cal.EventRecord} rec The original {@link Ext.ensible.cal.EventRecord record} for the event that was resized * @param {Object} data An object containing the new start and end dates that will be set into the event record if the * event is not canceled. Format of the object is: {StartDate: [date], EndDate: [date]} */ beforeeventresize: true, /** * @event eventresize * Fires after the user has drag-dropped the resize handle of an event and the resize operation is complete. If you need * to cancel the resize operation you should handle the {@link #beforeeventresize} event and return false from your handler function. * @param {Ext.ensible.cal.DayBodyView} this * @param {Ext.ensible.cal.EventRecord} rec The {@link Ext.ensible.cal.EventRecord record} for the event that was resized * containing the updated start and end dates */ eventresize: true, /** * @event dayclick * Fires after the user clicks within the view container and not on an event element. This is a cancelable event, so * returning false from a handler will cancel the click without displaying the event editor view. This could be useful * for validating that a user can only create events on certain days. * @param {Ext.ensible.cal.DayBodyView} this * @param {Date} dt The date/time that was clicked on * @param {Boolean} allday True if the day clicked on represents an all-day box, else false. Clicks within the * DayBodyView always return false for this param. * @param {Ext.Element} el The Element that was clicked on */ dayclick: true }); }, //private initDD : function(){ var cfg = { view: this, createText: this.ddCreateEventText, moveText: this.ddMoveEventText, resizeText: this.ddResizeEventText, ddIncrement: this.ddIncrement, ddGroup: this.ddGroup || this.id+'-DayViewDD' }; this.el.ddScrollConfig = { // scrolling is buggy in IE/Opera for some reason. A larger vthresh // makes it at least functional if not perfect vthresh: Ext.isIE || Ext.isOpera ? 100 : 40, hthresh: -1, frequency: 50, increment: 100, ddGroup: this.ddGroup || this.id+'-DayViewDD' }; this.dragZone = new Ext.ensible.cal.DayViewDragZone(this.el, Ext.apply({ containerScroll: true }, cfg)); this.dropZone = new Ext.ensible.cal.DayViewDropZone(this.el, cfg); }, //private refresh : function(reloadData){ Ext.ensible.log('refresh (DayBodyView)'); var top = this.el.getScroll().top; Ext.ensible.cal.DayBodyView.superclass.refresh.call(this, reloadData); // skip this if the initial render scroll position has not yet been set. // necessary since IE/Opera must be deferred, so the first refresh will // override the initial position by default and always set it to 0. if(this.scrollReady){ this.scrollTo(top); } }, /** * Scrolls the container to the specified vertical position. If the view is large enough that * there is no scroll overflow then this method will have no affect. * @param {Number} y The new vertical scroll position in pixels * @param {Boolean} defer (optional)True to slightly defer the call, false to execute immediately.
*This method will automatically defer itself for IE and Opera (even if you pass false) otherwise * the scroll position will not update in those browsers. You can optionally pass true, however, to * force the defer in all browsers, or use your own custom conditions to determine whether this is needed.
*Note that this method should not generally need to be called directly as scroll position is managed internally.
*/ scrollTo : function(y, defer){ defer = defer || (Ext.isIE || Ext.isOpera); if(defer){ (function(){ this.el.scrollTo('top', y); this.scrollReady = true; }).defer(10, this); } else{ this.el.scrollTo('top', y); this.scrollReady = true; } }, // private afterRender : function(){ if(!this.tpl){ this.tpl = new Ext.ensible.cal.DayBodyTemplate({ id: this.id, dayCount: this.dayCount, showTodayText: this.showTodayText, todayText: this.todayText, showTime: this.showTime, showHourSeparator: this.showHourSeparator, viewStartHour: this.viewStartHour, viewEndHour: this.viewEndHour, hourIncrement: this.hourIncrement, hourHeight: this.hourHeight }); } this.tpl.compile(); this.addClass('ext-cal-body-ct'); Ext.ensible.cal.DayBodyView.superclass.afterRender.call(this); // default scroll position to scrollStartHour (7am by default) or min view hour if later var startHour = Math.max(this.scrollStartHour, this.viewStartHour), scrollStart = Math.max(0, startHour - this.viewStartHour); if(scrollStart > 0){ this.scrollTo(scrollStart * this.hourHeight); } }, // private forceSize: Ext.emptyFn, // private -- called from DayViewDropZone onEventResize : function(rec, data){ if(this.fireEvent('beforeeventresize', this, rec, data) !== false){ var D = Ext.ensible.Date, start = Ext.ensible.cal.EventMappings.StartDate.name, end = Ext.ensible.cal.EventMappings.EndDate.name; if(D.compare(rec.data[start], data.StartDate) === 0 && D.compare(rec.data[end], data.EndDate) === 0){ // no changes return; } rec.set(start, data.StartDate); rec.set(end, data.EndDate); this.onEventUpdate(null, rec); this.fireEvent('eventresize', this, rec); } }, // inherited docs getEventBodyMarkup : function(){ if(!this.eventBodyMarkup){ this.eventBodyMarkup = ['{Title}', '', ' ', ' ', '', ' ', ' ' // '', // ' ', // ' ', // '', // ' ', // ' ' ].join(''); } return this.eventBodyMarkup; }, // inherited docs getEventTemplate : function(){ if(!this.eventTpl){ this.eventTpl = !(Ext.isIE || Ext.isOpera) ? new Ext.XTemplate( '', '' ) : new Ext.XTemplate( '', this.getEventBodyMarkup(), '', this.enableEventResize ? '' : '', '', '' ); this.eventTpl.compile(); } return this.eventTpl; }, /** *', '', '
', '- ', this.getEventBodyMarkup(), '
', this.enableEventResize ? '' : '', '', 'Returns the XTemplate that is bound to the calendar's event store (it expects records of type * {@link Ext.ensible.cal.EventRecord}) to populate the calendar views with all-day events. * Internally this method by default generates different markup for browsers that support CSS border radius * and those that don't. This method can be overridden as needed to customize the markup generated.
*Note that this method calls {@link #getEventBodyMarkup} to retrieve the body markup for events separately * from the surrounding container markup. This provdes the flexibility to customize what's in the body without * having to override the entire XTemplate. If you do override this method, you should make sure that your * overridden version also does the same.
* @return {Ext.XTemplate} The event XTemplate */ getEventAllDayTemplate : function(){ if(!this.eventAllDayTpl){ var tpl, body = this.getEventBodyMarkup(); tpl = !(Ext.isIE || Ext.isOpera) ? new Ext.XTemplate( '', body, '' ) : new Ext.XTemplate( '', '' ); tpl.compile(); this.eventAllDayTpl = tpl; } return this.eventAllDayTpl; }, // private getTemplateEventData : function(evt){ var M = Ext.ensible.cal.EventMappings, extraClasses = [this.getEventSelectorCls(evt[M.EventId.name])], data = {}, colorCls = 'x-cal-default', title = evt[M.Title.name], fmt = Ext.ensible.Date.use24HourTime ? 'G:i ' : 'g:ia ', recurring = evt[M.RRule.name] != ''; this.getTemplateEventBox(evt); if(this.calendarStore && evt[M.CalendarId.name]){ var rec = this.calendarStore.getById(evt[M.CalendarId.name]); if(rec){ colorCls = 'x-cal-' + rec.data[Ext.ensible.cal.CalendarMappings.ColorId.name]; } } colorCls += (evt._renderAsAllDay ? '-ad' : '') + (Ext.isIE || Ext.isOpera ? '-x' : ''); extraClasses.push(colorCls); if(this.getEventClass){ var rec = this.getEventRecord(evt[M.EventId.name]), cls = this.getEventClass(rec, !!evt._renderAsAllDay, data, this.store); extraClasses.push(cls); } data._extraCls = extraClasses.join(' '); data._isRecurring = evt.Recurrence && evt.Recurrence != ''; data._isReminder = evt[M.Reminder.name] && evt[M.Reminder.name] != ''; data.Title = (evt[M.IsAllDay.name] ? '' : evt[M.StartDate.name].format(fmt)) + (!title || title.length == 0 ? this.defaultEventTitleText : title); return Ext.applyIf(data, evt); }, // private getEventPositionOffsets: function(){ return { top: 1, height: -2 } }, // private getTemplateEventBox : function(evt){ var heightFactor = this.hourHeight / this.hourIncrement, start = evt[Ext.ensible.cal.EventMappings.StartDate.name], end = evt[Ext.ensible.cal.EventMappings.EndDate.name], startOffset = Math.max(start.getHours() - this.viewStartHour, 0), endOffset = Math.min(end.getHours() - this.viewStartHour, this.viewEndHour - this.viewStartHour), startMins = startOffset * this.hourIncrement, endMins = endOffset * this.hourIncrement, viewEndDt = end.clearTime(true).add(Date.HOUR, this.viewEndHour), evtOffsets = this.getEventPositionOffsets(); if(start.getHours() >= this.viewStartHour){ // only add the minutes if the start is visible, otherwise it offsets the event incorrectly startMins += start.getMinutes(); } if(end <= viewEndDt){ // only add the minutes if the end is visible, otherwise it offsets the event incorrectly endMins += end.getMinutes(); } evt._left = 0; evt._width = 100; evt._top = startMins * heightFactor + evtOffsets.top; evt._height = Math.max(((endMins - startMins) * heightFactor), this.minEventHeight) + evtOffsets.height; }, // private renderItems: function(){ var day = 0, evts = []; for(; day < this.dayCount; day++){ var ev = emptyCells = skipped = 0, d = this.eventGrid[0][day], ct = d ? d.length : 0, evt; for(; ev < ct; ev++){ evt = d[ev]; if(!evt){ continue; } var item = evt.data || evt.event.data, M = Ext.ensible.cal.EventMappings, ad = item[M.IsAllDay.name] === true, span = Ext.ensible.Date.diffDays(item[M.StartDate.name], item[M.EndDate.name]) > 0, renderAsAllDay = ad || span; if(renderAsAllDay){ // this event is already rendered in the header view continue; } Ext.apply(item, { cls: 'ext-cal-ev', _positioned: true }); evts.push({ data: this.getTemplateEventData(item), date: this.viewStart.add(Date.DAY, day) }); } } // overlapping event pre-processing loop var i = j = 0, overlapCols = [], l = evts.length, prevDt; for(; i', '', '', '', body, '', '-1){ var dt = this.getDateFromId(el.id, this.dayElIdDelimiter); this.onDayClick(Date.parseDate(dt, 'Ymd'), true, Ext.get(this.getDayId(dt))); return; } } var day = this.getDayAt(e.xy[0], e.xy[1]); if(day && day.date){ this.onDayClick(day.date, false, null); } } }); Ext.reg('extensible.daybodyview', Ext.ensible.cal.DayBodyView);