--- /dev/null
+/*!
+ * Ext JS Library 3.3.1
+ * Copyright(c) 2006-2010 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+/**\r
+ * @class Ext.calendar.MonthView\r
+ * @extends Ext.calendar.CalendarView\r
+ * <p>Displays a calendar view by month. This class does not usually need ot be used directly as you can\r
+ * use a {@link Ext.calendar.CalendarPanel CalendarPanel} to manage multiple calendar views at once including\r
+ * the month view.</p>\r
+ * @constructor\r
+ * @param {Object} config The config object\r
+ */\r
+Ext.calendar.MonthView = Ext.extend(Ext.calendar.CalendarView, {\r
+ /**\r
+ * @cfg {Boolean} showTime\r
+ * True to display the current time in today's box in the calendar, false to not display it (defautls to true)\r
+ */\r
+ showTime: true,\r
+ /**\r
+ * @cfg {Boolean} showTodayText\r
+ * True to display the {@link #todayText} string in today's box in the calendar, false to not display it (defautls to true)\r
+ */\r
+ showTodayText: true,\r
+ /**\r
+ * @cfg {String} todayText\r
+ * The text to display in the current day's box in the calendar when {@link #showTodayText} is true (defaults to 'Today')\r
+ */\r
+ todayText: 'Today',\r
+ /**\r
+ * @cfg {Boolean} showHeader\r
+ * True to display a header beneath the navigation bar containing the week names above each week's column, false not to \r
+ * show it and instead display the week names in the first row of days in the calendar (defaults to false).\r
+ */\r
+ showHeader: false,\r
+ /**\r
+ * @cfg {Boolean} showWeekLinks\r
+ * True to display an extra column before the first day in the calendar that links to the {@link Ext.calendar.WeekView view}\r
+ * for each individual week, false to not show it (defaults to false). If true, the week links can also contain the week \r
+ * number depending on the value of {@link #showWeekNumbers}.\r
+ */\r
+ showWeekLinks: false,\r
+ /**\r
+ * @cfg {Boolean} showWeekNumbers\r
+ * True to show the week number for each week in the calendar in the week link column, false to show nothing (defaults to false).\r
+ * Note that if {@link #showWeekLinks} is false this config will have no affect even if true.\r
+ */\r
+ showWeekNumbers: false,\r
+ /**\r
+ * @cfg {String} weekLinkOverClass\r
+ * The CSS class name applied when the mouse moves over a week link element (only applies when {@link #showWeekLinks} is true,\r
+ * defaults to 'ext-week-link-over').\r
+ */\r
+ weekLinkOverClass: 'ext-week-link-over',\r
+\r
+ //private properties -- do not override:\r
+ daySelector: '.ext-cal-day',\r
+ moreSelector: '.ext-cal-ev-more',\r
+ weekLinkSelector: '.ext-cal-week-link',\r
+ weekCount: -1,\r
+ // defaults to auto by month\r
+ dayCount: 7,\r
+ moreElIdDelimiter: '-more-',\r
+ weekLinkIdDelimiter: 'ext-cal-week-',\r
+\r
+ // private\r
+ initComponent: function() {\r
+ Ext.calendar.MonthView.superclass.initComponent.call(this);\r
+ this.addEvents({\r
+ /**\r
+ * @event dayclick\r
+ * Fires after the user clicks within the view container and not on an event element\r
+ * @param {Ext.calendar.MonthView} this\r
+ * @param {Date} dt The date/time that was clicked on\r
+ * @param {Boolean} allday True if the day clicked on represents an all-day box, else false. Clicks within the \r
+ * MonthView always return true for this param.\r
+ * @param {Ext.Element} el The Element that was clicked on\r
+ */\r
+ dayclick: true,\r
+ /**\r
+ * @event weekclick\r
+ * Fires after the user clicks within a week link (when {@link #showWeekLinks is true)\r
+ * @param {Ext.calendar.MonthView} this\r
+ * @param {Date} dt The start date of the week that was clicked on\r
+ */\r
+ weekclick: true,\r
+ // inherited docs\r
+ dayover: true,\r
+ // inherited docs\r
+ dayout: true\r
+ });\r
+ },\r
+\r
+ // private\r
+ initDD: function() {\r
+ var cfg = {\r
+ view: this,\r
+ createText: this.ddCreateEventText,\r
+ moveText: this.ddMoveEventText,\r
+ ddGroup: 'MonthViewDD'\r
+ };\r
+\r
+ this.dragZone = new Ext.calendar.DragZone(this.el, cfg);\r
+ this.dropZone = new Ext.calendar.DropZone(this.el, cfg);\r
+ },\r
+\r
+ // private\r
+ onDestroy: function() {\r
+ Ext.destroy(this.ddSelector);\r
+ Ext.destroy(this.dragZone);\r
+ Ext.destroy(this.dropZone);\r
+ Ext.calendar.MonthView.superclass.onDestroy.call(this);\r
+ },\r
+\r
+ // private\r
+ afterRender: function() {\r
+ if (!this.tpl) {\r
+ this.tpl = new Ext.calendar.MonthViewTemplate({\r
+ id: this.id,\r
+ showTodayText: this.showTodayText,\r
+ todayText: this.todayText,\r
+ showTime: this.showTime,\r
+ showHeader: this.showHeader,\r
+ showWeekLinks: this.showWeekLinks,\r
+ showWeekNumbers: this.showWeekNumbers\r
+ });\r
+ }\r
+ this.tpl.compile();\r
+ this.addClass('ext-cal-monthview ext-cal-ct');\r
+\r
+ Ext.calendar.MonthView.superclass.afterRender.call(this);\r
+ },\r
+\r
+ // private\r
+ onResize: function() {\r
+ if (this.monitorResize) {\r
+ this.maxEventsPerDay = this.getMaxEventsPerDay();\r
+ this.refresh();\r
+ }\r
+ },\r
+\r
+ // private\r
+ forceSize: function() {\r
+ // Compensate for the week link gutter width if visible\r
+ if (this.showWeekLinks && this.el && this.el.child) {\r
+ var hd = this.el.select('.ext-cal-hd-days-tbl'),\r
+ bgTbl = this.el.select('.ext-cal-bg-tbl'),\r
+ evTbl = this.el.select('.ext-cal-evt-tbl'),\r
+ wkLinkW = this.el.child('.ext-cal-week-link').getWidth(),\r
+ w = this.el.getWidth() - wkLinkW;\r
+\r
+ hd.setWidth(w);\r
+ bgTbl.setWidth(w);\r
+ evTbl.setWidth(w);\r
+ }\r
+ Ext.calendar.MonthView.superclass.forceSize.call(this);\r
+ },\r
+\r
+ //private\r
+ initClock: function() {\r
+ if (Ext.fly(this.id + '-clock') !== null) {\r
+ this.prevClockDay = new Date().getDay();\r
+ if (this.clockTask) {\r
+ Ext.TaskMgr.stop(this.clockTask);\r
+ }\r
+ this.clockTask = Ext.TaskMgr.start({\r
+ run: function() {\r
+ var el = Ext.fly(this.id + '-clock'),\r
+ t = new Date();\r
+\r
+ if (t.getDay() == this.prevClockDay) {\r
+ if (el) {\r
+ el.update(t.format('g:i a'));\r
+ }\r
+ }\r
+ else {\r
+ this.prevClockDay = t.getDay();\r
+ this.moveTo(t);\r
+ }\r
+ },\r
+ scope: this,\r
+ interval: 1000\r
+ });\r
+ }\r
+ },\r
+\r
+ // inherited docs\r
+ getEventBodyMarkup: function() {\r
+ if (!this.eventBodyMarkup) {\r
+ this.eventBodyMarkup = ['{Title}',\r
+ '<tpl if="_isReminder">',\r
+ '<i class="ext-cal-ic ext-cal-ic-rem"> </i>',\r
+ '</tpl>',\r
+ '<tpl if="_isRecurring">',\r
+ '<i class="ext-cal-ic ext-cal-ic-rcr"> </i>',\r
+ '</tpl>',\r
+ '<tpl if="spanLeft">',\r
+ '<i class="ext-cal-spl"> </i>',\r
+ '</tpl>',\r
+ '<tpl if="spanRight">',\r
+ '<i class="ext-cal-spr"> </i>',\r
+ '</tpl>'\r
+ ].join('');\r
+ }\r
+ return this.eventBodyMarkup;\r
+ },\r
+\r
+ // inherited docs\r
+ getEventTemplate: function() {\r
+ if (!this.eventTpl) {\r
+ var tpl,\r
+ body = this.getEventBodyMarkup();\r
+\r
+ tpl = !(Ext.isIE || Ext.isOpera) ?\r
+ new Ext.XTemplate(\r
+ '<div id="{_elId}" class="{_selectorCls} {_colorCls} {values.spanCls} ext-cal-evt ext-cal-evr">',\r
+ body,\r
+ '</div>'\r
+ )\r
+ : new Ext.XTemplate(\r
+ '<tpl if="_renderAsAllDay">',\r
+ '<div id="{_elId}" class="{_selectorCls} {values.spanCls} {_colorCls} ext-cal-evt ext-cal-evo">',\r
+ '<div class="ext-cal-evm">',\r
+ '<div class="ext-cal-evi">',\r
+ '</tpl>',\r
+ '<tpl if="!_renderAsAllDay">',\r
+ '<div id="{_elId}" class="{_selectorCls} {_colorCls} ext-cal-evt ext-cal-evr">',\r
+ '</tpl>',\r
+ body,\r
+ '<tpl if="_renderAsAllDay">',\r
+ '</div>',\r
+ '</div>',\r
+ '</tpl>',\r
+ '</div>'\r
+ );\r
+ tpl.compile();\r
+ this.eventTpl = tpl;\r
+ }\r
+ return this.eventTpl;\r
+ },\r
+\r
+ // private\r
+ getTemplateEventData: function(evt) {\r
+ var M = Ext.calendar.EventMappings,\r
+ selector = this.getEventSelectorCls(evt[M.EventId.name]),\r
+ title = evt[M.Title.name];\r
+\r
+ return Ext.applyIf({\r
+ _selectorCls: selector,\r
+ _colorCls: 'ext-color-' + (evt[M.CalendarId.name] ?\r
+ evt[M.CalendarId.name] : 'default') + (evt._renderAsAllDay ? '-ad': ''),\r
+ _elId: selector + '-' + evt._weekIndex,\r
+ _isRecurring: evt.Recurrence && evt.Recurrence != '',\r
+ _isReminder: evt[M.Reminder.name] && evt[M.Reminder.name] != '',\r
+ Title: (evt[M.IsAllDay.name] ? '': evt[M.StartDate.name].format('g:ia ')) + (!title || title.length == 0 ? '(No title)': title)\r
+ },\r
+ evt);\r
+ },\r
+\r
+ // private\r
+ refresh: function() {\r
+ if (this.detailPanel) {\r
+ this.detailPanel.hide();\r
+ }\r
+ Ext.calendar.MonthView.superclass.refresh.call(this);\r
+\r
+ if (this.showTime !== false) {\r
+ this.initClock();\r
+ }\r
+ },\r
+\r
+ // private\r
+ renderItems: function() {\r
+ Ext.calendar.WeekEventRenderer.render({\r
+ eventGrid: this.allDayOnly ? this.allDayGrid: this.eventGrid,\r
+ viewStart: this.viewStart,\r
+ tpl: this.getEventTemplate(),\r
+ maxEventsPerDay: this.maxEventsPerDay,\r
+ id: this.id,\r
+ templateDataFn: this.getTemplateEventData.createDelegate(this),\r
+ evtMaxCount: this.evtMaxCount,\r
+ weekCount: this.weekCount,\r
+ dayCount: this.dayCount\r
+ });\r
+ this.fireEvent('eventsrendered', this);\r
+ },\r
+\r
+ // private\r
+ getDayEl: function(dt) {\r
+ return Ext.get(this.getDayId(dt));\r
+ },\r
+\r
+ // private\r
+ getDayId: function(dt) {\r
+ if (Ext.isDate(dt)) {\r
+ dt = dt.format('Ymd');\r
+ }\r
+ return this.id + this.dayElIdDelimiter + dt;\r
+ },\r
+\r
+ // private\r
+ getWeekIndex: function(dt) {\r
+ var el = this.getDayEl(dt).up('.ext-cal-wk-ct');\r
+ return parseInt(el.id.split('-wk-')[1], 10);\r
+ },\r
+\r
+ // private\r
+ getDaySize: function(contentOnly) {\r
+ var box = this.el.getBox(),\r
+ w = box.width / this.dayCount,\r
+ h = box.height / this.getWeekCount();\r
+\r
+ if (contentOnly) {\r
+ var hd = this.el.select('.ext-cal-dtitle').first().parent('tr');\r
+ h = hd ? h - hd.getHeight(true) : h;\r
+ }\r
+ return {\r
+ height: h,\r
+ width: w\r
+ };\r
+ },\r
+\r
+ // private\r
+ getEventHeight: function() {\r
+ if (!this.eventHeight) {\r
+ var evt = this.el.select('.ext-cal-evt').first();\r
+ this.eventHeight = evt ? evt.parent('tr').getHeight() : 18;\r
+ }\r
+ return this.eventHeight;\r
+ },\r
+\r
+ // private\r
+ getMaxEventsPerDay: function() {\r
+ var dayHeight = this.getDaySize(true).height,\r
+ h = this.getEventHeight(),\r
+ max = Math.max(Math.floor((dayHeight - h) / h), 0);\r
+\r
+ return max;\r
+ },\r
+\r
+ // private\r
+ getDayAt: function(x, y) {\r
+ var box = this.el.getBox(),\r
+ daySize = this.getDaySize(),\r
+ dayL = Math.floor(((x - box.x) / daySize.width)),\r
+ dayT = Math.floor(((y - box.y) / daySize.height)),\r
+ days = (dayT * 7) + dayL,\r
+ dt = this.viewStart.add(Date.DAY, days);\r
+ return {\r
+ date: dt,\r
+ el: this.getDayEl(dt)\r
+ };\r
+ },\r
+\r
+ // inherited docs\r
+ moveNext: function() {\r
+ return this.moveMonths(1);\r
+ },\r
+\r
+ // inherited docs\r
+ movePrev: function() {\r
+ return this.moveMonths( - 1);\r
+ },\r
+\r
+ // private\r
+ onInitDrag: function() {\r
+ Ext.calendar.MonthView.superclass.onInitDrag.call(this);\r
+ Ext.select(this.daySelector).removeClass(this.dayOverClass);\r
+ if (this.detailPanel) {\r
+ this.detailPanel.hide();\r
+ }\r
+ },\r
+\r
+ // private\r
+ onMoreClick: function(dt) {\r
+ if (!this.detailPanel) {\r
+ this.detailPanel = new Ext.Panel({\r
+ id: this.id + '-details-panel',\r
+ title: dt.format('F j'),\r
+ layout: 'fit',\r
+ floating: true,\r
+ renderTo: Ext.getBody(),\r
+ tools: [{\r
+ id: 'close',\r
+ handler: function(e, t, p) {\r
+ p.hide();\r
+ }\r
+ }],\r
+ items: {\r
+ xtype: 'monthdaydetailview',\r
+ id: this.id + '-details-view',\r
+ date: dt,\r
+ view: this,\r
+ store: this.store,\r
+ listeners: {\r
+ 'eventsrendered': this.onDetailViewUpdated.createDelegate(this)\r
+ }\r
+ }\r
+ });\r
+ }\r
+ else {\r
+ this.detailPanel.setTitle(dt.format('F j'));\r
+ }\r
+ this.detailPanel.getComponent(this.id + '-details-view').update(dt);\r
+ },\r
+\r
+ // private\r
+ onDetailViewUpdated: function(view, dt, numEvents) {\r
+ var p = this.detailPanel,\r
+ frameH = p.getFrameHeight(),\r
+ evtH = this.getEventHeight(),\r
+ bodyH = frameH + (numEvents * evtH) + 3,\r
+ dayEl = this.getDayEl(dt),\r
+ box = dayEl.getBox();\r
+\r
+ p.updateBox(box);\r
+ p.setHeight(bodyH);\r
+ p.setWidth(Math.max(box.width, 220));\r
+ p.show();\r
+ p.getPositionEl().alignTo(dayEl, 't-t?');\r
+ },\r
+\r
+ // private\r
+ onHide: function() {\r
+ Ext.calendar.MonthView.superclass.onHide.call(this);\r
+ if (this.detailPanel) {\r
+ this.detailPanel.hide();\r
+ }\r
+ },\r
+\r
+ // private\r
+ onClick: function(e, t) {\r
+ if (this.detailPanel) {\r
+ this.detailPanel.hide();\r
+ }\r
+ if (Ext.calendar.MonthView.superclass.onClick.apply(this, arguments)) {\r
+ // The superclass handled the click already so exit\r
+ return;\r
+ }\r
+ if (this.dropZone) {\r
+ this.dropZone.clearShims();\r
+ }\r
+ var el = e.getTarget(this.weekLinkSelector, 3),\r
+ dt,\r
+ parts;\r
+ if (el) {\r
+ dt = el.id.split(this.weekLinkIdDelimiter)[1];\r
+ this.fireEvent('weekclick', this, Date.parseDate(dt, 'Ymd'));\r
+ return;\r
+ }\r
+ el = e.getTarget(this.moreSelector, 3);\r
+ if (el) {\r
+ dt = el.id.split(this.moreElIdDelimiter)[1];\r
+ this.onMoreClick(Date.parseDate(dt, 'Ymd'));\r
+ return;\r
+ }\r
+ el = e.getTarget('td', 3);\r
+ if (el) {\r
+ if (el.id && el.id.indexOf(this.dayElIdDelimiter) > -1) {\r
+ parts = el.id.split(this.dayElIdDelimiter);\r
+ dt = parts[parts.length - 1];\r
+\r
+ this.fireEvent('dayclick', this, Date.parseDate(dt, 'Ymd'), false, Ext.get(this.getDayId(dt)));\r
+ return;\r
+ }\r
+ }\r
+ },\r
+\r
+ // private\r
+ handleDayMouseEvent: function(e, t, type) {\r
+ var el = e.getTarget(this.weekLinkSelector, 3, true);\r
+ if (el) {\r
+ el[type == 'over' ? 'addClass': 'removeClass'](this.weekLinkOverClass);\r
+ return;\r
+ }\r
+ Ext.calendar.MonthView.superclass.handleDayMouseEvent.apply(this, arguments);\r
+ }\r
+});\r
+\r
+Ext.reg('monthview', Ext.calendar.MonthView);\r