    /*!
     * Ext JS Library 3.3.0
     * Copyright(c) 2006-2010 Ext JS, Inc.
     * licensing@extjs.com
     * http://www.extjs.com/license
     */
    /*
     * Internal drag zone implementation for the calendar components. This provides base functionality
     * and is primarily for the month view -- DayViewDD adds day/week view-specific functionality.
     */
    Ext.calendar.DragZone = Ext.extend(Ext.dd.DragZone, {
        ddGroup: 'CalendarDD',
        eventSelector: '.ext-cal-evt',

        constructor: function(el, config) {
            if (!Ext.calendar._statusProxyInstance) {
                Ext.calendar._statusProxyInstance = new Ext.calendar.StatusProxy();
            }
            this.proxy = Ext.calendar._statusProxyInstance;
            Ext.calendar.DragZone.superclass.constructor.call(this, el, config);
        },

        getDragData: function(e) {
            // Check whether we are dragging on an event first
            var t = e.getTarget(this.eventSelector, 3);
            if (t) {
                var rec = this.view.getEventRecordFromEl(t);
                return {
                    type: 'eventdrag',
                    ddel: t,
                    eventStart: rec.data[Ext.calendar.EventMappings.StartDate.name],
                    eventEnd: rec.data[Ext.calendar.EventMappings.EndDate.name],
                    proxy: this.proxy
                };
            }

            // If not dragging an event then we are dragging on
            // the calendar to add a new event
            t = this.view.getDayAt(e.getPageX(), e.getPageY());
            if (t.el) {
                return {
                    type: 'caldrag',
                    start: t.date,
                    proxy: this.proxy
                };
            }
            return null;
        },

        onInitDrag: function(x, y) {
            if (this.dragData.ddel) {
                var ghost = this.dragData.ddel.cloneNode(true),
                child = Ext.fly(ghost).child('dl');

                Ext.fly(ghost).setWidth('auto');

                if (child) {
                    // for IE/Opera
                    child.setHeight('auto');
                }
                this.proxy.update(ghost);
                this.onStartDrag(x, y);
            }
            else if (this.dragData.start) {
                this.onStartDrag(x, y);
            }
            this.view.onInitDrag();
            return true;
        },

        afterRepair: function() {
            if (Ext.enableFx && this.dragData.ddel) {
                Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || 'c3daf9');
            }
            this.dragging = false;
        },

        getRepairXY: function(e) {
            if (this.dragData.ddel) {
                return Ext.Element.fly(this.dragData.ddel).getXY();
            }
        },

        afterInvalidDrop: function(e, id) {
            Ext.select('.ext-dd-shim').hide();
        }
    });

    /*
     * Internal drop zone implementation for the calendar components. This provides base functionality
     * and is primarily for the month view -- DayViewDD adds day/week view-specific functionality.
     */
    Ext.calendar.DropZone = Ext.extend(Ext.dd.DropZone, {
        ddGroup: 'CalendarDD',
        eventSelector: '.ext-cal-evt',

        // private
        shims: [],

        getTargetFromEvent: function(e) {
            var dragOffset = this.dragOffset || 0,
            y = e.getPageY() - dragOffset,
            d = this.view.getDayAt(e.getPageX(), y);

            return d.el ? d: null;
        },

        onNodeOver: function(n, dd, e, data) {
            var D = Ext.calendar.Date,
            start = data.type == 'eventdrag' ? n.date: D.min(data.start, n.date),
            end = data.type == 'eventdrag' ? n.date.add(Date.DAY, D.diffDays(data.eventStart, data.eventEnd)) :
            D.max(data.start, n.date);

            if (!this.dragStartDate || !this.dragEndDate || (D.diffDays(start, this.dragStartDate) != 0) || (D.diffDays(end, this.dragEndDate) != 0)) {
                this.dragStartDate = start;
                this.dragEndDate = end.clearTime().add(Date.DAY, 1).add(Date.MILLI, -1);
                this.shim(start, end);

                var range = start.format('n/j');
                if (D.diffDays(start, end) > 0) {
                    range += '-' + end.format('n/j');
                }
                var msg = String.format(data.type == 'eventdrag' ? this.moveText: this.createText, range);
                data.proxy.updateMsg(msg);
            }
            return this.dropAllowed;
        },

        shim: function(start, end) {
            this.currWeek = -1;
            var dt = start.clone(),
                i = 0,
                shim,
                box,
                cnt = Ext.calendar.Date.diffDays(dt, end) + 1;

            Ext.each(this.shims,
                function(shim) {
                    if (shim) {
                        shim.isActive = false;
                    }
                }
            );

            while (i++