Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / examples / calendar / src / views / CalendarView.js
diff --git a/examples/calendar/src/views/CalendarView.js b/examples/calendar/src/views/CalendarView.js
deleted file mode 100644 (file)
index 8902514..0000000
+++ /dev/null
@@ -1,1023 +0,0 @@
-/*!
- * Ext JS Library 3.3.1
- * Copyright(c) 2006-2010 Sencha Inc.
- * licensing@sencha.com
- * http://www.sencha.com/license
- */
-/**\r
- * @class Ext.calendar.CalendarView\r
- * @extends Ext.BoxComponent\r
- * <p>This is an abstract class that serves as the base for other calendar views. This class is not\r
- * intended to be directly instantiated.</p>\r
- * <p>When extending this class to create a custom calendar view, you must provide an implementation\r
- * for the <code>renderItems</code> method, as there is no default implementation for rendering events\r
- * The rendering logic is totally dependent on how the UI structures its data, which\r
- * is determined by the underlying UI template (this base class does not have a template).</p>\r
- * @constructor\r
- * @param {Object} config The config object\r
- */\r
-Ext.calendar.CalendarView = Ext.extend(Ext.BoxComponent, {\r
-    /**\r
-     * @cfg {Number} startDay\r
-     * The 0-based index for the day on which the calendar week begins (0=Sunday, which is the default)\r
-     */\r
-    startDay: 0,\r
-    /**\r
-     * @cfg {Boolean} spansHavePriority\r
-     * Allows switching between two different modes of rendering events that span multiple days. When true,\r
-     * span events are always sorted first, possibly at the expense of start dates being out of order (e.g., \r
-     * a span event that starts at 11am one day and spans into the next day would display before a non-spanning \r
-     * event that starts at 10am, even though they would not be in date order). This can lead to more compact\r
-     * layouts when there are many overlapping events. If false (the default), events will always sort by start date\r
-     * first which can result in a less compact, but chronologically consistent layout.\r
-     */\r
-    spansHavePriority: false,\r
-    /**\r
-     * @cfg {Boolean} trackMouseOver\r
-     * Whether or not the view tracks and responds to the browser mouseover event on contained elements (defaults to\r
-     * true). If you don't need mouseover event highlighting you can disable this.\r
-     */\r
-    trackMouseOver: true,\r
-    /**\r
-     * @cfg {Boolean} enableFx\r
-     * Determines whether or not visual effects for CRUD actions are enabled (defaults to true). If this is false\r
-     * it will override any values for {@link #enableAddFx}, {@link #enableUpdateFx} or {@link enableRemoveFx} and\r
-     * all animations will be disabled.\r
-     */\r
-    enableFx: true,\r
-    /**\r
-     * @cfg {Boolean} enableAddFx\r
-     * True to enable a visual effect on adding a new event (the default), false to disable it. Note that if \r
-     * {@link #enableFx} is false it will override this value. The specific effect that runs is defined in the\r
-     * {@link #doAddFx} method.\r
-     */\r
-    enableAddFx: true,\r
-    /**\r
-     * @cfg {Boolean} enableUpdateFx\r
-     * True to enable a visual effect on updating an event, false to disable it (the default). Note that if \r
-     * {@link #enableFx} is false it will override this value. The specific effect that runs is defined in the\r
-     * {@link #doUpdateFx} method.\r
-     */\r
-    enableUpdateFx: false,\r
-    /**\r
-     * @cfg {Boolean} enableRemoveFx\r
-     * True to enable a visual effect on removing an event (the default), false to disable it. Note that if \r
-     * {@link #enableFx} is false it will override this value. The specific effect that runs is defined in the\r
-     * {@link #doRemoveFx} method.\r
-     */\r
-    enableRemoveFx: true,\r
-    /**\r
-     * @cfg {Boolean} enableDD\r
-     * True to enable drag and drop in the calendar view (the default), false to disable it\r
-     */\r
-    enableDD: true,\r
-    /**\r
-     * @cfg {Boolean} monitorResize\r
-     * True to monitor the browser's resize event (the default), false to ignore it. If the calendar view is rendered\r
-     * into a fixed-size container this can be set to false. However, if the view can change dimensions (e.g., it's in \r
-     * fit layout in a viewport or some other resizable container) it is very important that this config is true so that\r
-     * any resize event propagates properly to all subcomponents and layouts get recalculated properly.\r
-     */\r
-    monitorResize: true,\r
-    /**\r
-     * @cfg {String} ddCreateEventText\r
-     * The text to display inside the drag proxy while dragging over the calendar to create a new event (defaults to \r
-     * 'Create event for {0}' where {0} is a date range supplied by the view)\r
-     */\r
-    ddCreateEventText: 'Create event for {0}',\r
-    /**\r
-     * @cfg {String} ddMoveEventText\r
-     * The text to display inside the drag proxy while dragging an event to reposition it (defaults to \r
-     * 'Move event to {0}' where {0} is the updated event start date/time supplied by the view)\r
-     */\r
-    ddMoveEventText: 'Move event to {0}',\r
-    /**\r
-     * @cfg {String} ddResizeEventText\r
-     * The string displayed to the user in the drag proxy while dragging the resize handle of an event (defaults to \r
-     * 'Update event to {0}' where {0} is the updated event start-end range supplied by the view). Note that \r
-     * this text is only used in views\r
-     * that allow resizing of events.\r
-     */\r
-    ddResizeEventText: 'Update event to {0}',\r
-\r
-    //private properties -- do not override:\r
-    weekCount: 1,\r
-    dayCount: 1,\r
-    eventSelector: '.ext-cal-evt',\r
-    eventOverClass: 'ext-evt-over',\r
-    eventElIdDelimiter: '-evt-',\r
-    dayElIdDelimiter: '-day-',\r
-\r
-    /**\r
-     * Returns a string of HTML template markup to be used as the body portion of the event template created\r
-     * by {@link #getEventTemplate}. This provdes the flexibility to customize what's in the body without\r
-     * having to override the entire XTemplate. This string can include any valid {@link Ext.Template} code, and\r
-     * any data tokens accessible to the containing event template can be referenced in this string.\r
-     * @return {String} The body template string\r
-     */\r
-    getEventBodyMarkup: Ext.emptyFn,\r
-    // must be implemented by a subclass\r
-    /**\r
-     * <p>Returns the XTemplate that is bound to the calendar's event store (it expects records of type\r
-     * {@link Ext.calendar.EventRecord}) to populate the calendar views with events. Internally this method\r
-     * by default generates different markup for browsers that support CSS border radius and those that don't.\r
-     * This method can be overridden as needed to customize the markup generated.</p>\r
-     * <p>Note that this method calls {@link #getEventBodyMarkup} to retrieve the body markup for events separately\r
-     * from the surrounding container markup.  This provdes the flexibility to customize what's in the body without\r
-     * having to override the entire XTemplate. If you do override this method, you should make sure that your \r
-     * overridden version also does the same.</p>\r
-     * @return {Ext.XTemplate} The event XTemplate\r
-     */\r
-    getEventTemplate: Ext.emptyFn,\r
-    // must be implemented by a subclass\r
-    // private\r
-    initComponent: function() {\r
-        this.setStartDate(this.startDate || new Date());\r
-\r
-        Ext.calendar.CalendarView.superclass.initComponent.call(this);\r
-\r
-        this.addEvents({\r
-            /**\r
-             * @event eventsrendered\r
-             * Fires after events are finished rendering in the view\r
-             * @param {Ext.calendar.CalendarView} this \r
-             */\r
-            eventsrendered: true,\r
-            /**\r
-             * @event eventclick\r
-             * Fires after the user clicks on an event element\r
-             * @param {Ext.calendar.CalendarView} this\r
-             * @param {Ext.calendar.EventRecord} rec The {@link Ext.calendar.EventRecord record} for the event that was clicked on\r
-             * @param {HTMLNode} el The DOM node that was clicked on\r
-             */\r
-            eventclick: true,\r
-            /**\r
-             * @event eventover\r
-             * Fires anytime the mouse is over an event element\r
-             * @param {Ext.calendar.CalendarView} this\r
-             * @param {Ext.calendar.EventRecord} rec The {@link Ext.calendar.EventRecord record} for the event that the cursor is over\r
-             * @param {HTMLNode} el The DOM node that is being moused over\r
-             */\r
-            eventover: true,\r
-            /**\r
-             * @event eventout\r
-             * Fires anytime the mouse exits an event element\r
-             * @param {Ext.calendar.CalendarView} this\r
-             * @param {Ext.calendar.EventRecord} rec The {@link Ext.calendar.EventRecord record} for the event that the cursor exited\r
-             * @param {HTMLNode} el The DOM node that was exited\r
-             */\r
-            eventout: true,\r
-            /**\r
-             * @event datechange\r
-             * Fires after the start date of the view changes\r
-             * @param {Ext.calendar.CalendarView} this\r
-             * @param {Date} startDate The start date of the view (as explained in {@link #getStartDate}\r
-             * @param {Date} viewStart The first displayed date in the view\r
-             * @param {Date} viewEnd The last displayed date in the view\r
-             */\r
-            datechange: true,\r
-            /**\r
-             * @event rangeselect\r
-             * Fires after the user drags on the calendar to select a range of dates/times in which to create an event\r
-             * @param {Ext.calendar.CalendarView} this\r
-             * @param {Object} dates An object containing the start (StartDate property) and end (EndDate property) dates selected\r
-             * @param {Function} callback A callback function that MUST be called after the event handling is complete so that\r
-             * the view is properly cleaned up (shim elements are persisted in the view while the user is prompted to handle the\r
-             * range selection). The callback is already created in the proper scope, so it simply needs to be executed as a standard\r
-             * function call (e.g., callback()).\r
-             */\r
-            rangeselect: true,\r
-            /**\r
-             * @event eventmove\r
-             * Fires after an event element is dragged by the user and dropped in a new position\r
-             * @param {Ext.calendar.CalendarView} this\r
-             * @param {Ext.calendar.EventRecord} rec The {@link Ext.calendar.EventRecord record} for the event that was moved with\r
-             * updated start and end dates\r
-             */\r
-            eventmove: true,\r
-            /**\r
-             * @event initdrag\r
-             * Fires when a drag operation is initiated in the view\r
-             * @param {Ext.calendar.CalendarView} this\r
-             */\r
-            initdrag: true,\r
-            /**\r
-             * @event dayover\r
-             * Fires while the mouse is over a day element \r
-             * @param {Ext.calendar.CalendarView} this\r
-             * @param {Date} dt The date that is being moused over\r
-             * @param {Ext.Element} el The day Element that is being moused over\r
-             */\r
-            dayover: true,\r
-            /**\r
-             * @event dayout\r
-             * Fires when the mouse exits a day element \r
-             * @param {Ext.calendar.CalendarView} this\r
-             * @param {Date} dt The date that is exited\r
-             * @param {Ext.Element} el The day Element that is exited\r
-             */\r
-            dayout: true\r
-            /*\r
-             * @event eventdelete\r
-             * Fires after an event element is deleted by the user. Not currently implemented directly at the view level -- currently \r
-             * deletes only happen from one of the forms.\r
-             * @param {Ext.calendar.CalendarView} this\r
-             * @param {Ext.calendar.EventRecord} rec The {@link Ext.calendar.EventRecord record} for the event that was deleted\r
-             */\r
-            //eventdelete: true\r
-        });\r
-    },\r
-\r
-    // private\r
-    afterRender: function() {\r
-        Ext.calendar.CalendarView.superclass.afterRender.call(this);\r
-\r
-        this.renderTemplate();\r
-\r
-        if (this.store) {\r
-            this.setStore(this.store, true);\r
-        }\r
-\r
-        this.el.on({\r
-            'mouseover': this.onMouseOver,\r
-            'mouseout': this.onMouseOut,\r
-            'click': this.onClick,\r
-            'resize': this.onResize,\r
-            scope: this\r
-        });\r
-\r
-        this.el.unselectable();\r
-\r
-        if (this.enableDD && this.initDD) {\r
-            this.initDD();\r
-        }\r
-\r
-        this.on('eventsrendered', this.forceSize);\r
-        this.forceSize.defer(100, this);\r
-\r
-    },\r
-\r
-    // private\r
-    forceSize: function() {\r
-        if (this.el && this.el.child) {\r
-            var hd = this.el.child('.ext-cal-hd-ct'),\r
-            bd = this.el.child('.ext-cal-body-ct');\r
-\r
-            if (bd == null || hd == null) return;\r
-\r
-            var headerHeight = hd.getHeight(),\r
-            sz = this.el.parent().getSize();\r
-\r
-            bd.setHeight(sz.height - headerHeight);\r
-        }\r
-    },\r
-\r
-    refresh: function() {\r
-        this.prepareData();\r
-        this.renderTemplate();\r
-        this.renderItems();\r
-    },\r
-\r
-    getWeekCount: function() {\r
-        var days = Ext.calendar.Date.diffDays(this.viewStart, this.viewEnd);\r
-        return Math.ceil(days / this.dayCount);\r
-    },\r
-\r
-    // private\r
-    prepareData: function() {\r
-        var lastInMonth = this.startDate.getLastDateOfMonth(),\r
-        w = 0,\r
-        row = 0,\r
-        dt = this.viewStart.clone(),\r
-        weeks = this.weekCount < 1 ? 6: this.weekCount;\r
-\r
-        this.eventGrid = [[]];\r
-        this.allDayGrid = [[]];\r
-        this.evtMaxCount = [];\r
-\r
-        var evtsInView = this.store.queryBy(function(rec) {\r
-            return this.isEventVisible(rec.data);\r
-        },\r
-        this);\r
-\r
-        for (; w < weeks; w++) {\r
-            this.evtMaxCount[w] = 0;\r
-            if (this.weekCount == -1 && dt > lastInMonth) {\r
-                //current week is fully in next month so skip\r
-                break;\r
-            }\r
-            this.eventGrid[w] = this.eventGrid[w] || [];\r
-            this.allDayGrid[w] = this.allDayGrid[w] || [];\r
-\r
-            for (d = 0; d < this.dayCount; d++) {\r
-                if (evtsInView.getCount() > 0) {\r
-                    var evts = evtsInView.filterBy(function(rec) {\r
-                        var startsOnDate = (dt.getTime() == rec.data[Ext.calendar.EventMappings.StartDate.name].clearTime(true).getTime());\r
-                        var spansFromPrevView = (w == 0 && d == 0 && (dt > rec.data[Ext.calendar.EventMappings.StartDate.name]));\r
-                        return startsOnDate || spansFromPrevView;\r
-                    },\r
-                    this);\r
-\r
-                    this.sortEventRecordsForDay(evts);\r
-                    this.prepareEventGrid(evts, w, d);\r
-                }\r
-                dt = dt.add(Date.DAY, 1);\r
-            }\r
-        }\r
-        this.currentWeekCount = w;\r
-    },\r
-\r
-    // private\r
-    prepareEventGrid: function(evts, w, d) {\r
-        var row = 0,\r
-        dt = this.viewStart.clone(),\r
-        max = this.maxEventsPerDay ? this.maxEventsPerDay: 999;\r
-\r
-        evts.each(function(evt) {\r
-            var M = Ext.calendar.EventMappings,\r
-            days = Ext.calendar.Date.diffDays(\r
-            Ext.calendar.Date.max(this.viewStart, evt.data[M.StartDate.name]),\r
-            Ext.calendar.Date.min(this.viewEnd, evt.data[M.EndDate.name])) + 1;\r
-\r
-            if (days > 1 || Ext.calendar.Date.diffDays(evt.data[M.StartDate.name], evt.data[M.EndDate.name]) > 1) {\r
-                this.prepareEventGridSpans(evt, this.eventGrid, w, d, days);\r
-                this.prepareEventGridSpans(evt, this.allDayGrid, w, d, days, true);\r
-            } else {\r
-                row = this.findEmptyRowIndex(w, d);\r
-                this.eventGrid[w][d] = this.eventGrid[w][d] || [];\r
-                this.eventGrid[w][d][row] = evt;\r
-\r
-                if (evt.data[M.IsAllDay.name]) {\r
-                    row = this.findEmptyRowIndex(w, d, true);\r
-                    this.allDayGrid[w][d] = this.allDayGrid[w][d] || [];\r
-                    this.allDayGrid[w][d][row] = evt;\r
-                }\r
-            }\r
-\r
-            if (this.evtMaxCount[w] < this.eventGrid[w][d].length) {\r
-                this.evtMaxCount[w] = Math.min(max + 1, this.eventGrid[w][d].length);\r
-            }\r
-            return true;\r
-        },\r
-        this);\r
-    },\r
-\r
-    // private\r
-    prepareEventGridSpans: function(evt, grid, w, d, days, allday) {\r
-        // this event spans multiple days/weeks, so we have to preprocess\r
-        // the events and store special span events as placeholders so that\r
-        // the render routine can build the necessary TD spans correctly.\r
-        var w1 = w,\r
-        d1 = d,\r
-        row = this.findEmptyRowIndex(w, d, allday),\r
-        dt = this.viewStart.clone();\r
-\r
-        var start = {\r
-            event: evt,\r
-            isSpan: true,\r
-            isSpanStart: true,\r
-            spanLeft: false,\r
-            spanRight: (d == 6)\r
-        };\r
-        grid[w][d] = grid[w][d] || [];\r
-        grid[w][d][row] = start;\r
-\r
-        while (--days) {\r
-            dt = dt.add(Date.DAY, 1);\r
-            if (dt > this.viewEnd) {\r
-                break;\r
-            }\r
-            if (++d1 > 6) {\r
-                // reset counters to the next week\r
-                d1 = 0;\r
-                w1++;\r
-                row = this.findEmptyRowIndex(w1, 0);\r
-            }\r
-            grid[w1] = grid[w1] || [];\r
-            grid[w1][d1] = grid[w1][d1] || [];\r
-\r
-            grid[w1][d1][row] = {\r
-                event: evt,\r
-                isSpan: true,\r
-                isSpanStart: (d1 == 0),\r
-                spanLeft: (w1 > w) && (d1 % 7 == 0),\r
-                spanRight: (d1 == 6) && (days > 1)\r
-            };\r
-        }\r
-    },\r
-\r
-    // private\r
-    findEmptyRowIndex: function(w, d, allday) {\r
-        var grid = allday ? this.allDayGrid: this.eventGrid,\r
-        day = grid[w] ? grid[w][d] || [] : [],\r
-        i = 0,\r
-        ln = day.length;\r
-\r
-        for (; i < ln; i++) {\r
-            if (day[i] == null) {\r
-                return i;\r
-            }\r
-        }\r
-        return ln;\r
-    },\r
-\r
-    // private\r
-    renderTemplate: function() {\r
-        if (this.tpl) {\r
-            this.tpl.overwrite(this.el, this.getParams());\r
-            this.lastRenderStart = this.viewStart.clone();\r
-            this.lastRenderEnd = this.viewEnd.clone();\r
-        }\r
-    },\r
-\r
-    disableStoreEvents: function() {\r
-        this.monitorStoreEvents = false;\r
-    },\r
-\r
-    enableStoreEvents: function(refresh) {\r
-        this.monitorStoreEvents = true;\r
-        if (refresh === true) {\r
-            this.refresh();\r
-        }\r
-    },\r
-\r
-    // private\r
-    onResize: function() {\r
-        this.refresh();\r
-    },\r
-\r
-    // private\r
-    onInitDrag: function() {\r
-        this.fireEvent('initdrag', this);\r
-    },\r
-\r
-    // private\r
-    onEventDrop: function(rec, dt) {\r
-        if (Ext.calendar.Date.compare(rec.data[Ext.calendar.EventMappings.StartDate.name], dt) === 0) {\r
-            // no changes\r
-            return;\r
-        }\r
-        var diff = dt.getTime() - rec.data[Ext.calendar.EventMappings.StartDate.name].getTime();\r
-        rec.set(Ext.calendar.EventMappings.StartDate.name, dt);\r
-        rec.set(Ext.calendar.EventMappings.EndDate.name, rec.data[Ext.calendar.EventMappings.EndDate.name].add(Date.MILLI, diff));\r
-\r
-        this.fireEvent('eventmove', this, rec);\r
-    },\r
-\r
-    // private\r
-    onCalendarEndDrag: function(start, end, onComplete) {\r
-        // set this flag for other event handlers that might conflict while we're waiting\r
-        this.dragPending = true;\r
-\r
-        // have to wait for the user to save or cancel before finalizing the dd interation\r
-        var o = {};\r
-        o[Ext.calendar.EventMappings.StartDate.name] = start;\r
-        o[Ext.calendar.EventMappings.EndDate.name] = end;\r
-\r
-        this.fireEvent('rangeselect', this, o, this.onCalendarEndDragComplete.createDelegate(this, [onComplete]));\r
-    },\r
-\r
-    // private\r
-    onCalendarEndDragComplete: function(onComplete) {\r
-        // callback for the drop zone to clean up\r
-        onComplete();\r
-        // clear flag for other events to resume normally\r
-        this.dragPending = false;\r
-    },\r
-\r
-    // private\r
-    onUpdate: function(ds, rec, operation) {\r
-        if (this.monitorStoreEvents === false) {\r
-            return;\r
-        }\r
-        if (operation == Ext.data.Record.COMMIT) {\r
-            this.refresh();\r
-            if (this.enableFx && this.enableUpdateFx) {\r
-                this.doUpdateFx(this.getEventEls(rec.data[Ext.calendar.EventMappings.EventId.name]), {\r
-                    scope: this\r
-                });\r
-            }\r
-        }\r
-    },\r
-\r
-\r
-    doUpdateFx: function(els, o) {\r
-        this.highlightEvent(els, null, o);\r
-    },\r
-\r
-    // private\r
-    onAdd: function(ds, records, index) {\r
-        if (this.monitorStoreEvents === false) {\r
-            return;\r
-        }\r
-        var rec = records[0];\r
-        this.tempEventId = rec.id;\r
-        this.refresh();\r
-\r
-        if (this.enableFx && this.enableAddFx) {\r
-            this.doAddFx(this.getEventEls(rec.data[Ext.calendar.EventMappings.EventId.name]), {\r
-                scope: this\r
-            });\r
-        };\r
-    },\r
-\r
-    doAddFx: function(els, o) {\r
-        els.fadeIn(Ext.apply(o, {\r
-            duration: 2\r
-        }));\r
-    },\r
-\r
-    // private\r
-    onRemove: function(ds, rec) {\r
-        if (this.monitorStoreEvents === false) {\r
-            return;\r
-        }\r
-        if (this.enableFx && this.enableRemoveFx) {\r
-            this.doRemoveFx(this.getEventEls(rec.data[Ext.calendar.EventMappings.EventId.name]), {\r
-                remove: true,\r
-                scope: this,\r
-                callback: this.refresh\r
-            });\r
-        }\r
-        else {\r
-            this.getEventEls(rec.data[Ext.calendar.EventMappings.EventId.name]).remove();\r
-            this.refresh();\r
-        }\r
-    },\r
-\r
-    doRemoveFx: function(els, o) {\r
-        els.fadeOut(o);\r
-    },\r
-\r
-    /**\r
-     * Visually highlights an event using {@link Ext.Fx#highlight} config options.\r
-     * If {@link #highlightEventActions} is false this method will have no effect.\r
-     * @param {Ext.CompositeElement} els The element(s) to highlight\r
-     * @param {Object} color (optional) The highlight color. Should be a 6 char hex \r
-     * color without the leading # (defaults to yellow: 'ffff9c')\r
-     * @param {Object} o (optional) Object literal with any of the {@link Ext.Fx} config \r
-     * options. See {@link Ext.Fx#highlight} for usage examples.\r
-     */\r
-    highlightEvent: function(els, color, o) {\r
-        if (this.enableFx) {\r
-            var c;\r
-            ! (Ext.isIE || Ext.isOpera) ?\r
-            els.highlight(color, o) :\r
-            // Fun IE/Opera handling:\r
-            els.each(function(el) {\r
-                el.highlight(color, Ext.applyIf({\r
-                    attr: 'color'\r
-                },\r
-                o));\r
-                c = el.child('.ext-cal-evm');\r
-                if (c) {\r
-                    c.highlight(color, o);\r
-                }\r
-            },\r
-            this);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Retrieve an Event object's id from its corresponding node in the DOM.\r
-     * @param {String/Element/HTMLElement} el An {@link Ext.Element}, DOM node or id\r
-     */\r
-    getEventIdFromEl: function(el) {\r
-        el = Ext.get(el);\r
-        var id = el.id.split(this.eventElIdDelimiter)[1];\r
-        if (id.indexOf('-') > -1) {\r
-            //This id has the index of the week it is rendered in as the suffix.\r
-            //This allows events that span across weeks to still have reproducibly-unique DOM ids.\r
-            id = id.split('-')[0];\r
-        }\r
-        return id;\r
-    },\r
-\r
-    // private\r
-    getEventId: function(eventId) {\r
-        if (eventId === undefined && this.tempEventId) {\r
-            eventId = this.tempEventId;\r
-        }\r
-        return eventId;\r
-    },\r
-\r
-    /**\r
-     * \r
-     * @param {String} eventId\r
-     * @param {Boolean} forSelect\r
-     * @return {String} The selector class\r
-     */\r
-    getEventSelectorCls: function(eventId, forSelect) {\r
-        var prefix = forSelect ? '.': '';\r
-        return prefix + this.id + this.eventElIdDelimiter + this.getEventId(eventId);\r
-    },\r
-\r
-    /**\r
-     * \r
-     * @param {String} eventId\r
-     * @return {Ext.CompositeElement} The matching CompositeElement of nodes\r
-     * that comprise the rendered event.  Any event that spans across a view \r
-     * boundary will contain more than one internal Element.\r
-     */\r
-    getEventEls: function(eventId) {\r
-        var els = Ext.select(this.getEventSelectorCls(this.getEventId(eventId), true), false, this.el.id);\r
-        return new Ext.CompositeElement(els);\r
-    },\r
-\r
-    /**\r
-     * Returns true if the view is currently displaying today's date, else false.\r
-     * @return {Boolean} True or false\r
-     */\r
-    isToday: function() {\r
-        var today = new Date().clearTime().getTime();\r
-        return this.viewStart.getTime() <= today && this.viewEnd.getTime() >= today;\r
-    },\r
-\r
-    // private\r
-    onDataChanged: function(store) {\r
-        this.refresh();\r
-    },\r
-\r
-    // private\r
-    isEventVisible: function(evt) {\r
-        var start = this.viewStart.getTime(),\r
-        end = this.viewEnd.getTime(),\r
-        M = Ext.calendar.EventMappings,\r
-        evStart = (evt.data ? evt.data[M.StartDate.name] : evt[M.StartDate.name]).getTime(),\r
-        evEnd = (evt.data ? evt.data[M.EndDate.name] : evt[M.EndDate.name]).add(Date.SECOND, -1).getTime(),\r
-\r
-        startsInRange = (evStart >= start && evStart <= end),\r
-        endsInRange = (evEnd >= start && evEnd <= end),\r
-        spansRange = (evStart < start && evEnd > end);\r
-\r
-        return (startsInRange || endsInRange || spansRange);\r
-    },\r
-\r
-    // private\r
-    isOverlapping: function(evt1, evt2) {\r
-        var ev1 = evt1.data ? evt1.data: evt1,\r
-        ev2 = evt2.data ? evt2.data: evt2,\r
-        M = Ext.calendar.EventMappings,\r
-        start1 = ev1[M.StartDate.name].getTime(),\r
-        end1 = ev1[M.EndDate.name].add(Date.SECOND, -1).getTime(),\r
-        start2 = ev2[M.StartDate.name].getTime(),\r
-        end2 = ev2[M.EndDate.name].add(Date.SECOND, -1).getTime();\r
-\r
-        if (end1 < start1) {\r
-            end1 = start1;\r
-        }\r
-        if (end2 < start2) {\r
-            end2 = start2;\r
-        }\r
-\r
-        var ev1startsInEv2 = (start1 >= start2 && start1 <= end2),\r
-        ev1EndsInEv2 = (end1 >= start2 && end1 <= end2),\r
-        ev1SpansEv2 = (start1 < start2 && end1 > end2);\r
-\r
-        return (ev1startsInEv2 || ev1EndsInEv2 || ev1SpansEv2);\r
-    },\r
-\r
-    getDayEl: function(dt) {\r
-        return Ext.get(this.getDayId(dt));\r
-    },\r
-\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
-    /**\r
-     * Returns the start date of the view, as set by {@link #setStartDate}. Note that this may not \r
-     * be the first date displayed in the rendered calendar -- to get the start and end dates displayed\r
-     * to the user use {@link #getViewBounds}.\r
-     * @return {Date} The start date\r
-     */\r
-    getStartDate: function() {\r
-        return this.startDate;\r
-    },\r
-\r
-    /**\r
-     * Sets the start date used to calculate the view boundaries to display. The displayed view will be the \r
-     * earliest and latest dates that match the view requirements and contain the date passed to this function.\r
-     * @param {Date} dt The date used to calculate the new view boundaries\r
-     */\r
-    setStartDate: function(start, refresh) {\r
-        this.startDate = start.clearTime();\r
-        this.setViewBounds(start);\r
-        this.store.load({\r
-            params: {\r
-                start: this.viewStart.format('m-d-Y'),\r
-                end: this.viewEnd.format('m-d-Y')\r
-            }\r
-        });\r
-        if (refresh === true) {\r
-            this.refresh();\r
-        }\r
-        this.fireEvent('datechange', this, this.startDate, this.viewStart, this.viewEnd);\r
-    },\r
-\r
-    // private\r
-    setViewBounds: function(startDate) {\r
-        var start = startDate || this.startDate,\r
-        offset = start.getDay() - this.startDay;\r
-\r
-        switch (this.weekCount) {\r
-        case 0:\r
-        case 1:\r
-            this.viewStart = this.dayCount < 7 ? start: start.add(Date.DAY, -offset).clearTime(true);\r
-            this.viewEnd = this.viewStart.add(Date.DAY, this.dayCount || 7).add(Date.SECOND, -1);\r
-            return;\r
-\r
-        case - 1:\r
-            // auto by month\r
-            start = start.getFirstDateOfMonth();\r
-            offset = start.getDay() - this.startDay;\r
-            if (offset < 0) {\r
-                offset += 7;\r
-            }\r
-            this.viewStart = start.add(Date.DAY, -offset).clearTime(true);\r
-\r
-            // start from current month start, not view start:\r
-            var end = start.add(Date.MONTH, 1).add(Date.SECOND, -1);\r
-            // fill out to the end of the week:\r
-            this.viewEnd = end.add(Date.DAY, 6 - end.getDay());\r
-            return;\r
-\r
-        default:\r
-            this.viewStart = start.add(Date.DAY, -offset).clearTime(true);\r
-            this.viewEnd = this.viewStart.add(Date.DAY, this.weekCount * 7).add(Date.SECOND, -1);\r
-        }\r
-    },\r
-\r
-    // private\r
-    getViewBounds: function() {\r
-        return {\r
-            start: this.viewStart,\r
-            end: this.viewEnd\r
-        };\r
-    },\r
-\r
-    /* private\r
-     * Sort events for a single day for display in the calendar.  This sorts allday\r
-     * events first, then non-allday events are sorted either based on event start\r
-     * priority or span priority based on the value of {@link #spansHavePriority} \r
-     * (defaults to event start priority).\r
-     * @param {MixedCollection} evts A {@link Ext.util.MixedCollection MixedCollection}  \r
-     * of {@link #Ext.calendar.EventRecord EventRecord} objects\r
-     */\r
-    sortEventRecordsForDay: function(evts) {\r
-        if (evts.length < 2) {\r
-            return;\r
-        }\r
-        evts.sort('ASC',\r
-        function(evtA, evtB) {\r
-            var a = evtA.data,\r
-            b = evtB.data,\r
-            M = Ext.calendar.EventMappings;\r
-\r
-            // Always sort all day events before anything else\r
-            if (a[M.IsAllDay.name]) {\r
-                return - 1;\r
-            }\r
-            else if (b[M.IsAllDay.name]) {\r
-                return 1;\r
-            }\r
-            if (this.spansHavePriority) {\r
-                // This logic always weights span events higher than non-span events\r
-                // (at the possible expense of start time order). This seems to\r
-                // be the approach used by Google calendar and can lead to a more\r
-                // visually appealing layout in complex cases, but event order is\r
-                // not guaranteed to be consistent.\r
-                var diff = Ext.calendar.Date.diffDays;\r
-                if (diff(a[M.StartDate.name], a[M.EndDate.name]) > 0) {\r
-                    if (diff(b[M.StartDate.name], b[M.EndDate.name]) > 0) {\r
-                        // Both events are multi-day\r
-                        if (a[M.StartDate.name].getTime() == b[M.StartDate.name].getTime()) {\r
-                            // If both events start at the same time, sort the one\r
-                            // that ends later (potentially longer span bar) first\r
-                            return b[M.EndDate.name].getTime() - a[M.EndDate.name].getTime();\r
-                        }\r
-                        return a[M.StartDate.name].getTime() - b[M.StartDate.name].getTime();\r
-                    }\r
-                    return - 1;\r
-                }\r
-                else if (diff(b[M.StartDate.name], b[M.EndDate.name]) > 0) {\r
-                    return 1;\r
-                }\r
-                return a[M.StartDate.name].getTime() - b[M.StartDate.name].getTime();\r
-            }\r
-            else {\r
-                // Doing this allows span and non-span events to intermingle but\r
-                // remain sorted sequentially by start time. This seems more proper\r
-                // but can make for a less visually-compact layout when there are\r
-                // many such events mixed together closely on the calendar.\r
-                return a[M.StartDate.name].getTime() - b[M.StartDate.name].getTime();\r
-            }\r
-        }.createDelegate(this));\r
-    },\r
-\r
-    /**\r
-     * Updates the view to contain the passed date\r
-     * @param {Date} dt The date to display\r
-     */\r
-    moveTo: function(dt, noRefresh) {\r
-        if (Ext.isDate(dt)) {\r
-            this.setStartDate(dt);\r
-            if (noRefresh !== false) {\r
-                this.refresh();\r
-            }\r
-            return this.startDate;\r
-        }\r
-        return dt;\r
-    },\r
-\r
-    /**\r
-     * Updates the view to the next consecutive date(s)\r
-     */\r
-    moveNext: function(noRefresh) {\r
-        return this.moveTo(this.viewEnd.add(Date.DAY, 1));\r
-    },\r
-\r
-    /**\r
-     * Updates the view to the previous consecutive date(s)\r
-     */\r
-    movePrev: function(noRefresh) {\r
-        var days = Ext.calendar.Date.diffDays(this.viewStart, this.viewEnd) + 1;\r
-        return this.moveDays( - days, noRefresh);\r
-    },\r
-\r
-    /**\r
-     * Shifts the view by the passed number of months relative to the currently set date\r
-     * @param {Number} value The number of months (positive or negative) by which to shift the view\r
-     */\r
-    moveMonths: function(value, noRefresh) {\r
-        return this.moveTo(this.startDate.add(Date.MONTH, value), noRefresh);\r
-    },\r
-\r
-    /**\r
-     * Shifts the view by the passed number of weeks relative to the currently set date\r
-     * @param {Number} value The number of weeks (positive or negative) by which to shift the view\r
-     */\r
-    moveWeeks: function(value, noRefresh) {\r
-        return this.moveTo(this.startDate.add(Date.DAY, value * 7), noRefresh);\r
-    },\r
-\r
-    /**\r
-     * Shifts the view by the passed number of days relative to the currently set date\r
-     * @param {Number} value The number of days (positive or negative) by which to shift the view\r
-     */\r
-    moveDays: function(value, noRefresh) {\r
-        return this.moveTo(this.startDate.add(Date.DAY, value), noRefresh);\r
-    },\r
-\r
-    /**\r
-     * Updates the view to show today\r
-     */\r
-    moveToday: function(noRefresh) {\r
-        return this.moveTo(new Date(), noRefresh);\r
-    },\r
-\r
-    /**\r
-     * Sets the event store used by the calendar to display {@link Ext.calendar.EventRecord events}.\r
-     * @param {Ext.data.Store} store\r
-     */\r
-    setStore: function(store, initial) {\r
-        if (!initial && this.store) {\r
-            this.store.un("datachanged", this.onDataChanged, this);\r
-            this.store.un("add", this.onAdd, this);\r
-            this.store.un("remove", this.onRemove, this);\r
-            this.store.un("update", this.onUpdate, this);\r
-            this.store.un("clear", this.refresh, this);\r
-        }\r
-        if (store) {\r
-            store.on("datachanged", this.onDataChanged, this);\r
-            store.on("add", this.onAdd, this);\r
-            store.on("remove", this.onRemove, this);\r
-            store.on("update", this.onUpdate, this);\r
-            store.on("clear", this.refresh, this);\r
-        }\r
-        this.store = store;\r
-        if (store && store.getCount() > 0) {\r
-            this.refresh();\r
-        }\r
-    },\r
-\r
-    getEventRecord: function(id) {\r
-        var idx = this.store.find(Ext.calendar.EventMappings.EventId.name, id);\r
-        return this.store.getAt(idx);\r
-    },\r
-\r
-    getEventRecordFromEl: function(el) {\r
-        return this.getEventRecord(this.getEventIdFromEl(el));\r
-    },\r
-\r
-    // private\r
-    getParams: function() {\r
-        return {\r
-            viewStart: this.viewStart,\r
-            viewEnd: this.viewEnd,\r
-            startDate: this.startDate,\r
-            dayCount: this.dayCount,\r
-            weekCount: this.weekCount,\r
-            title: this.getTitle()\r
-        };\r
-    },\r
-\r
-    getTitle: function() {\r
-        return this.startDate.format('F Y');\r
-    },\r
-\r
-    /*\r
-     * Shared click handling.  Each specific view also provides view-specific\r
-     * click handling that calls this first.  This method returns true if it\r
-     * can handle the click (and so the subclass should ignore it) else false.\r
-     */\r
-    onClick: function(e, t) {\r
-        var el = e.getTarget(this.eventSelector, 5);\r
-        if (el) {\r
-            var id = this.getEventIdFromEl(el);\r
-            this.fireEvent('eventclick', this, this.getEventRecord(id), el);\r
-            return true;\r
-        }\r
-    },\r
-\r
-    // private\r
-    onMouseOver: function(e, t) {\r
-        if (this.trackMouseOver !== false && (this.dragZone == undefined || !this.dragZone.dragging)) {\r
-            if (!this.handleEventMouseEvent(e, t, 'over')) {\r
-                this.handleDayMouseEvent(e, t, 'over');\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    onMouseOut: function(e, t) {\r
-        if (this.trackMouseOver !== false && (this.dragZone == undefined || !this.dragZone.dragging)) {\r
-            if (!this.handleEventMouseEvent(e, t, 'out')) {\r
-                this.handleDayMouseEvent(e, t, 'out');\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    handleEventMouseEvent: function(e, t, type) {\r
-        var el = e.getTarget(this.eventSelector, 5, true),\r
-            rel,\r
-            els,\r
-            evtId;\r
-        if (el) {\r
-            rel = Ext.get(e.getRelatedTarget());\r
-            if (el == rel || el.contains(rel)) {\r
-                return true;\r
-            }\r
-\r
-            evtId = this.getEventIdFromEl(el);\r
-\r
-            if (this.eventOverClass != '') {\r
-                els = this.getEventEls(evtId);\r
-                els[type == 'over' ? 'addClass': 'removeClass'](this.eventOverClass);\r
-            }\r
-            this.fireEvent('event' + type, this, this.getEventRecord(evtId), el);\r
-            return true;\r
-        }\r
-        return false;\r
-    },\r
-\r
-    // private\r
-    getDateFromId: function(id, delim) {\r
-        var parts = id.split(delim);\r
-        return parts[parts.length - 1];\r
-    },\r
-\r
-    // private\r
-    handleDayMouseEvent: function(e, t, type) {\r
-        t = e.getTarget('td', 3);\r
-        if (t) {\r
-            if (t.id && t.id.indexOf(this.dayElIdDelimiter) > -1) {\r
-                var dt = this.getDateFromId(t.id, this.dayElIdDelimiter),\r
-                rel = Ext.get(e.getRelatedTarget()),\r
-                relTD,\r
-                relDate;\r
-\r
-                if (rel) {\r
-                    relTD = rel.is('td') ? rel: rel.up('td', 3);\r
-                    relDate = relTD && relTD.id ? this.getDateFromId(relTD.id, this.dayElIdDelimiter) : '';\r
-                }\r
-                if (!rel || dt != relDate) {\r
-                    var el = this.getDayEl(dt);\r
-                    if (el && this.dayOverClass != '') {\r
-                        el[type == 'over' ? 'addClass': 'removeClass'](this.dayOverClass);\r
-                    }\r
-                    this.fireEvent('day' + type, this, Date.parseDate(dt, "Ymd"), el);\r
-                }\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    renderItems: function() {\r
-        throw 'This method must be implemented by a subclass';\r
-    }\r
-});\r