    /** * This view is used to wrap multiple calendar views and allows * switching between and communicating with them through a * single interface. This class does not provide any additional UI * functionality, that is provided by {@link Ext.calendar.panel.Panel} which * wraps this component. */Ext.define('Ext.calendar.view.Multi', {    extend: 'Ext.container.Container',    xtype: 'calendar-multiview',     requires: [        'Ext.calendar.date.Util'    ],     layout: 'fit',     platformConfig: {        '!desktop':  {            compact: true        }    },     config: {        /**         * @cfg {Boolean} compact          * `true` to display in compact mode, typically used         * for smaller form factors.         */        compact: false,         /**         * @cfg {Object} [compactOptions]         * A series of config options for this class to set when this class is in         * {@link #compact} mode.         */        compactOptions: null,         /**         * @cfg {Object/Ext.calendar.store.Calendars} store         * A calendar store instance or configuration.         */        store: null,         /**         * @cfg {Number} timezoneOffset          * The timezone offset to display this calendar in. The value should be         * specified in the same way as the native Date offset. That is, the number         * of minutes between UTC and local time. For example the offset for UTC+10         * would be -600 (10 hours * 60 minutes ahead).         *         * Defaults to the current browser offset.         */        timezoneOffset: undefined,         /**         * @cfg {Date} value          * The value that controls the underlying {@link #views}.         */        value: undefined,         /**         * @cfg {Object} views          * The calendar views to have available, each item in         * this configuration (labelled by a key) is to contain         * the configuration for the view, a class that extends         * {@link Ext.calendar.panel.Base}.         */        views: null    },     defaultView: null,     constructor: function(config) {        this.callParent([config]);        var view = this.defaultView;        if (view) {            this.setView(view);        }    },     /**     * Moves the active view forward. The amount moved     * depends on the current view.     */    moveNext: function() {        this.setValue(this.activeView.calculateMoveNext());    },     /**     * Moves the active view backward. The amount moved     * depends on the current view.     */    movePrevious: function() {        this.setValue(this.activeView.calculateMovePrevious());    },     /**     * Move the current view by an amount based of the current {@link #value}.     * @param {Number} amount The number of intervals to move.     * @param {String} [interval=Ext.Date.DAY] The interval to navigate by. See {@link Ext.Date}     * for valid intervals.     */    navigate: function(amount, interval) {        var D = Ext.Date;        if (amount !== 0) {            this.setValue(D.add(this.getValue(), interval || D.DAY, amount));        }    },     setView: function(view) {        var me = this,            active = me.activeView,            cfg;         if (active && active.$key === view) {            return;        }         Ext.suspendLayouts();        if (active) {            me.remove(active);        }        cfg = me.getViews()[view];        //<debug>         if (!cfg) {            Ext.raise('Invalid view specified: "' + view + '".');        }        //</debug>         me.activeView = me.add(me.createView(cfg, view));        me.recalculate(me.getValue());         Ext.resumeLayouts(true);    },     // Appliers/Updaters     updateCompact: function(compact) {        this.setViewCfg('setCompact', compact);    },     applyStore: function(store) {        if (store) {            store = Ext.StoreManager.lookup(store, 'calendar-calendars');        }        return store;    },     updateStore: function(store) {        var me = this;         me.setViewCfg('setStore', store);        if (!me.isConfiguring) {            me.recalculate(me.getValue());        }    },     applyTimezoneOffset: function(timezoneOffset) {        if (timezoneOffset === undefined) {            timezoneOffset = Ext.calendar.date.Util.getDefaultTimezoneOffset();        }        return timezoneOffset;    },     updateTimezoneOffset: function(timezoneOffset) {        this.setViewCfg('setTimezoneOffset', timezoneOffset);    },     applyValue: function(value, oldValue) {        value = Ext.Date.clearTime(value || Ext.calendar.date.Util.getLocalNow(), true);        if (oldValue && oldValue.getTime() === value.getTime()) {            value = undefined;        }        return value;    },     updateValue: function(value) {        if (!this.isConfiguring) {            this.recalculate(value);        }    },        showAddForm: function(data, options) {        return this.activeView.showAddForm(data, options);    },        showEditForm: function(event, options) {        return this.activeView.showEditForm(event, options);    },     privates: {        createView: function(cfg, key) {            var me = this;             return Ext.apply({                $key: key,                controlStoreRange: false,                compact: me.getCompact(),                store: me.getStore(),                timezoneOffset: me.getTimezoneOffset(),                value: me.getValue(),                listeners: {                    scope: me,                    valuechange: 'onValueChange'                }            }, cfg);        },         getActiveKey: function() {            var active = this.activeView;            return active ? active.$key : '';        },                onValueChange: function(view, context) {            this.setValue(context.value);            this.fireEvent('valuechange', this, context);        },         recalculate: function(value) {            var view = this.activeView,                store = this.getStore(),                range, eventSource;             if (view && store) {                eventSource = store.getEventSource();                range = Ext.calendar.date.Util.expandRange(view.getView().doRecalculate(value).full);                 eventSource.setRange(range);                view.setValue(value);            }        },         setViewCfg: function(setterName, value) {            if (!this.isConfiguring) {                var view = this.activeView;                if (view) {                    view[setterName](value);                }            }        }    }});