API: calendar CalendarGroup.js (YUI Library)

# Yahoo! UI Library

### Calendar 2.8.0r4

Yahoo! UI Library > calendar > CalendarGroup.js (source view)
Search:
Filters Show Private Show Protected Show Deprecated

    (function() {

        var Dom = YAHOO.util.Dom,
            DateMath = YAHOO.widget.DateMath,
            Event = YAHOO.util.Event,
            Lang = YAHOO.lang,
            Calendar = YAHOO.widget.Calendar;

    /**
    * YAHOO.widget.CalendarGroup is a special container class for YAHOO.widget.Calendar. This class facilitates
    * the ability to have multi-page calendar views that share a single dataset and are
    * dependent on each other.
    *
    * The calendar group instance will refer to each of its elements using a 0-based index.
    * For example, to construct the placeholder for a calendar group widget with id "cal1" and
    * containerId of "cal1Container", the markup would be as follows:
    *   <xmp>
    *       <div id="cal1Container_0"></div>
    *       <div id="cal1Container_1"></div>
    *   </xmp>
    * The tables for the calendars ("cal1_0" and "cal1_1") will be inserted into those containers.
    *
    * <p>
    * <strong>NOTE: As of 2.4.0, the constructor's ID argument is optional.</strong>
    * The CalendarGroup can be constructed by simply providing a container ID string,
    * or a reference to a container DIV HTMLElement (the element needs to exist
    * in the document).
    *
    * E.g.:
    *   <xmp>
    *       var c = new YAHOO.widget.CalendarGroup("calContainer", configOptions);
    *   </xmp>
    * or:
    *   <xmp>
    *       var containerDiv = YAHOO.util.Dom.get("calContainer");
    *       var c = new YAHOO.widget.CalendarGroup(containerDiv, configOptions);
    *   </xmp>
    * </p>
    * <p>
    * If not provided, the ID will be generated from the container DIV ID by adding an "_t" suffix.
    * For example if an ID is not provided, and the container's ID is "calContainer", the CalendarGroup's ID will be set to "calContainer_t".
    * </p>
    *
    * @namespace YAHOO.widget
    * @class CalendarGroup
    * @constructor
    * @param {String} id optional The id of the table element that will represent the CalendarGroup widget. As of 2.4.0, this argument is optional.
    * @param {String | HTMLElement} container The id of the container div element that will wrap the CalendarGroup table, or a reference to a DIV element which exists in the document.
    * @param {Object} config optional The configuration object containing the initial configuration values for the CalendarGroup.
    */
    function CalendarGroup(id, containerId, config) {
        if (arguments.length > 0) {
            this.init.apply(this, arguments);
        }
    }

    /**
    * The set of default Config property keys and values for the CalendarGroup.
    *
    * <p>
    * NOTE: This property is made public in order to allow users to change
    * the default values of configuration properties. Users should not
    * modify the key string, unless they are overriding the Calendar implementation
    * </p>
    *
    * @property YAHOO.widget.CalendarGroup.DEFAULT_CONFIG
    * @static
    * @type Object An object with key/value pairs, the key being the
    * uppercase configuration property name and the value being an objec
    * literal with a key string property, and a value property, specifying the
    * default value of the property
    */

    /**
    * The set of default Config property keys and values for the CalendarGroup
    * @property YAHOO.widget.CalendarGroup._DEFAULT_CONFIG
    * @deprecated Made public. See the public DEFAULT_CONFIG property for details
    * @private
    * @static
    * @type Object
    */
    CalendarGroup.DEFAULT_CONFIG = CalendarGroup._DEFAULT_CONFIG = Calendar.DEFAULT_CONFIG;
    CalendarGroup.DEFAULT_CONFIG.PAGES = {key:"pages", value:2};

    var DEF_CFG = CalendarGroup.DEFAULT_CONFIG;

    CalendarGroup.prototype = {

        /**
        * Initializes the calendar group. All subclasses must call this method in order for the
        * group to be initialized properly.
        * @method init
        * @param {String} id optional The id of the table element that will represent the CalendarGroup widget. As of 2.4.0, this argument is optional.
        * @param {String | HTMLElement} container The id of the container div element that will wrap the CalendarGroup table, or a reference to a DIV element which exists in the document.
        * @param {Object} config optional The configuration object containing the initial configuration values for the CalendarGroup.
        */
        init : function(id, container, config) {

            // Normalize 2.4.0, pre 2.4.0 args
            var nArgs = this._parseArgs(arguments);

            id = nArgs.id;
            container = nArgs.container;
            config = nArgs.config;

            this.oDomContainer = Dom.get(container);
            if (!this.oDomContainer) { this.logger.log("Container not found in document.", "error"); }

            if (!this.oDomContainer.id) {
                this.oDomContainer.id = Dom.generateId();
            }
            if (!id) {
                id = this.oDomContainer.id + "_t";
            }

            /**
            * The unique id associated with the CalendarGroup
            * @property id
            * @type String
            */
            this.id = id;

            /**
            * The unique id associated with the CalendarGroup container
            * @property containerId
            * @type String
            */
            this.containerId = this.oDomContainer.id;

            this.logger = new YAHOO.widget.LogWriter("CalendarGroup " + this.id);
            this.initEvents();
            this.initStyles();

            /**
            * The collection of Calendar pages contained within the CalendarGroup
            * @property pages
            * @type YAHOO.widget.Calendar[]
            */
            this.pages = [];

            Dom.addClass(this.oDomContainer, CalendarGroup.CSS_CONTAINER);
            Dom.addClass(this.oDomContainer, CalendarGroup.CSS_MULTI_UP);

            /**
            * The Config object used to hold the configuration variables for the CalendarGroup
            * @property cfg
            * @type YAHOO.util.Config
            */
            this.cfg = new YAHOO.util.Config(this);

            /**
            * The local object which contains the CalendarGroup's options
            * @property Options
            * @type Object
            */
            this.Options = {};

            /**
            * The local object which contains the CalendarGroup's locale settings
            * @property Locale
            * @type Object
            */
            this.Locale = {};

            this.setupConfig();

            if (config) {
                this.cfg.applyConfig(config, true);
            }

            this.cfg.fireQueue();

            // OPERA HACK FOR MISWRAPPED FLOATS
            if (YAHOO.env.ua.opera){
                this.renderEvent.subscribe(this._fixWidth, this, true);
                this.showEvent.subscribe(this._fixWidth, this, true);
            }

            this.logger.log("Initialized " + this.pages.length + "-page CalendarGroup", "info");
        },

        setupConfig : function() {

            var cfg = this.cfg;

            /**
            * The number of pages to include in the CalendarGroup. This value can only be set once, in the CalendarGroup's constructor arguments.
            * @config pages
            * @type Number
            * @default 2
            */
            cfg.addProperty(DEF_CFG.PAGES.key, { value:DEF_CFG.PAGES.value, validator:cfg.checkNumber, handler:this.configPages } );

            /**
            * The positive or negative year offset from the Gregorian calendar year (assuming a January 1st rollover) to
            * be used when displaying or parsing dates.  NOTE: All JS Date objects returned by methods, or expected as input by
            * methods will always represent the Gregorian year, in order to maintain date/month/week values.
            *
            * @config year_offset
            * @type Number
            * @default 0
            */
            cfg.addProperty(DEF_CFG.YEAR_OFFSET.key, { value:DEF_CFG.YEAR_OFFSET.value, handler: this.delegateConfig, supercedes:DEF_CFG.YEAR_OFFSET.supercedes, suppressEvent:true } );

            /**
            * The date to use to represent "Today".
            *
            * @config today
            * @type Date
            * @default Today's date
            */
            cfg.addProperty(DEF_CFG.TODAY.key, { value: new Date(DEF_CFG.TODAY.value.getTime()), supercedes:DEF_CFG.TODAY.supercedes, handler: this.configToday, suppressEvent:false } );

            /**
            * The month/year representing the current visible Calendar date (mm/yyyy)
            * @config pagedate
            * @type String | Date
            * @default Today's date
            */
            cfg.addProperty(DEF_CFG.PAGEDATE.key, { value: DEF_CFG.PAGEDATE.value || new Date(DEF_CFG.TODAY.value.getTime()), handler:this.configPageDate } );

            /**
            * The date or range of dates representing the current Calendar selection
            *
            * @config selected
            * @type String
            * @default []
            */
            cfg.addProperty(DEF_CFG.SELECTED.key, { value:[], handler:this.configSelected } );

            /**
            * The title to display above the CalendarGroup's month header
            * @config title
            * @type String
            * @default ""
            */
            cfg.addProperty(DEF_CFG.TITLE.key, { value:DEF_CFG.TITLE.value, handler:this.configTitle } );

            /**
            * Whether or not a close button should be displayed for this CalendarGroup
            * @config close
            * @type Boolean
            * @default false
            */
            cfg.addProperty(DEF_CFG.CLOSE.key, { value:DEF_CFG.CLOSE.value, handler:this.configClose } );

            /**
            * Whether or not an iframe shim should be placed under the Calendar to prevent select boxes from bleeding through in Internet Explorer 6 and below.
            * This property is enabled by default for IE6 and below. It is disabled by default for other browsers for performance reasons, but can be
            * enabled if required.
            *
            * @config iframe
            * @type Boolean
            * @default true for IE6 and below, false for all other browsers
            */
            cfg.addProperty(DEF_CFG.IFRAME.key, { value:DEF_CFG.IFRAME.value, handler:this.configIframe, validator:cfg.checkBoolean } );

            /**
            * The minimum selectable date in the current Calendar (mm/dd/yyyy)
            * @config mindate
            * @type String | Date
            * @default null
            */
            cfg.addProperty(DEF_CFG.MINDATE.key, { value:DEF_CFG.MINDATE.value, handler:this.delegateConfig } );

            /**
            * The maximum selectable date in the current Calendar (mm/dd/yyyy)
            * @config maxdate
            * @type String | Date
            * @default null
            */
            cfg.addProperty(DEF_CFG.MAXDATE.key, { value:DEF_CFG.MAXDATE.value, handler:this.delegateConfig  } );

            // Options properties

            /**
            * True if the Calendar should allow multiple selections. False by default.
            * @config MULTI_SELECT
            * @type Boolean
            * @default false
            */
            cfg.addProperty(DEF_CFG.MULTI_SELECT.key, { value:DEF_CFG.MULTI_SELECT.value, handler:this.delegateConfig, validator:cfg.checkBoolean } );

            /**
            * The weekday the week begins on. Default is 0 (Sunday).
            * @config START_WEEKDAY
            * @type number
            * @default 0
            */
            cfg.addProperty(DEF_CFG.START_WEEKDAY.key, { value:DEF_CFG.START_WEEKDAY.value, handler:this.delegateConfig, validator:cfg.checkNumber  } );

            /**
            * True if the Calendar should show weekday labels. True by default.
            * @config SHOW_WEEKDAYS
            * @type Boolean
            * @default true
            */
            cfg.addProperty(DEF_CFG.SHOW_WEEKDAYS.key, { value:DEF_CFG.SHOW_WEEKDAYS.value, handler:this.delegateConfig, validator:cfg.checkBoolean } );

            /**
            * True if the Calendar should show week row headers. False by default.
            * @config SHOW_WEEK_HEADER
            * @type Boolean
            * @default false
            */
            cfg.addProperty(DEF_CFG.SHOW_WEEK_HEADER.key,{ value:DEF_CFG.SHOW_WEEK_HEADER.value, handler:this.delegateConfig, validator:cfg.checkBoolean } );

            /**
            * True if the Calendar should show week row footers. False by default.
            * @config SHOW_WEEK_FOOTER
            * @type Boolean
            * @default false
            */
            cfg.addProperty(DEF_CFG.SHOW_WEEK_FOOTER.key,{ value:DEF_CFG.SHOW_WEEK_FOOTER.value, handler:this.delegateConfig, validator:cfg.checkBoolean } );

            /**
            * True if the Calendar should suppress weeks that are not a part of the current month. False by default.
            * @config HIDE_BLANK_WEEKS
            * @type Boolean
            * @default false
            */
            cfg.addProperty(DEF_CFG.HIDE_BLANK_WEEKS.key,{ value:DEF_CFG.HIDE_BLANK_WEEKS.value, handler:this.delegateConfig, validator:cfg.checkBoolean } );

            /**
            * The image that should be used for the left navigation arrow.
            * @config NAV_ARROW_LEFT
            * @type String
            * @deprecated You can customize the image by overriding the default CSS class for the left arrow - "calnavleft"
            * @default null
            */
            cfg.addProperty(DEF_CFG.NAV_ARROW_LEFT.key, { value:DEF_CFG.NAV_ARROW_LEFT.value, handler:this.delegateConfig } );

            /**
            * The image that should be used for the right navigation arrow.
            * @config NAV_ARROW_RIGHT
            * @type String
            * @deprecated You can customize the image by overriding the default CSS class for the right arrow - "calnavright"
            * @default null
            */
            cfg.addProperty(DEF_CFG.NAV_ARROW_RIGHT.key, { value:DEF_CFG.NAV_ARROW_RIGHT.value, handler:this.delegateConfig } );

            // Locale properties

            /**
            * The short month labels for the current locale.
            * @config MONTHS_SHORT
            * @type String[]
            * @default ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
            */
            cfg.addProperty(DEF_CFG.MONTHS_SHORT.key, { value:DEF_CFG.MONTHS_SHORT.value, handler:this.delegateConfig } );

            /**
            * The long month labels for the current locale.
            * @config MONTHS_LONG
            * @type String[]
            * @default ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
            */
            cfg.addProperty(DEF_CFG.MONTHS_LONG.key,  { value:DEF_CFG.MONTHS_LONG.value, handler:this.delegateConfig } );

            /**
            * The 1-character weekday labels for the current locale.
            * @config WEEKDAYS_1CHAR
            * @type String[]
            * @default ["S", "M", "T", "W", "T", "F", "S"]
            */
            cfg.addProperty(DEF_CFG.WEEKDAYS_1CHAR.key, { value:DEF_CFG.WEEKDAYS_1CHAR.value, handler:this.delegateConfig } );

            /**
            * The short weekday labels for the current locale.
            * @config WEEKDAYS_SHORT
            * @type String[]
            * @default ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]
            */
            cfg.addProperty(DEF_CFG.WEEKDAYS_SHORT.key, { value:DEF_CFG.WEEKDAYS_SHORT.value, handler:this.delegateConfig } );

            /**
            * The medium weekday labels for the current locale.
            * @config WEEKDAYS_MEDIUM
            * @type String[]
            * @default ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
            */
            cfg.addProperty(DEF_CFG.WEEKDAYS_MEDIUM.key, { value:DEF_CFG.WEEKDAYS_MEDIUM.value, handler:this.delegateConfig } );

            /**
            * The long weekday labels for the current locale.
            * @config WEEKDAYS_LONG
            * @type String[]
            * @default ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
            */
            cfg.addProperty(DEF_CFG.WEEKDAYS_LONG.key, { value:DEF_CFG.WEEKDAYS_LONG.value, handler:this.delegateConfig } );

            /**
            * The setting that determines which length of month labels should be used. Possible values are "short" and "long".
            * @config LOCALE_MONTHS
            * @type String
            * @default "long"
            */
            cfg.addProperty(DEF_CFG.LOCALE_MONTHS.key, { value:DEF_CFG.LOCALE_MONTHS.value, handler:this.delegateConfig } );

            /**
            * The setting that determines which length of weekday labels should be used. Possible values are "1char", "short", "medium", and "long".
            * @config LOCALE_WEEKDAYS
            * @type String
            * @default "short"
            */
            cfg.addProperty(DEF_CFG.LOCALE_WEEKDAYS.key, { value:DEF_CFG.LOCALE_WEEKDAYS.value, handler:this.delegateConfig } );

            /**
            * The value used to delimit individual dates in a date string passed to various Calendar functions.
            * @config DATE_DELIMITER
            * @type String
            * @default ","
            */
            cfg.addProperty(DEF_CFG.DATE_DELIMITER.key,  { value:DEF_CFG.DATE_DELIMITER.value, handler:this.delegateConfig } );

            /**
            * The value used to delimit date fields in a date string passed to various Calendar functions.
            * @config DATE_FIELD_DELIMITER
            * @type String
            * @default "/"
            */
            cfg.addProperty(DEF_CFG.DATE_FIELD_DELIMITER.key,{ value:DEF_CFG.DATE_FIELD_DELIMITER.value, handler:this.delegateConfig } );

            /**
            * The value used to delimit date ranges in a date string passed to various Calendar functions.
            * @config DATE_RANGE_DELIMITER
            * @type String
            * @default "-"
            */
            cfg.addProperty(DEF_CFG.DATE_RANGE_DELIMITER.key,{ value:DEF_CFG.DATE_RANGE_DELIMITER.value, handler:this.delegateConfig } );

            /**
            * The position of the month in a month/year date string
            * @config MY_MONTH_POSITION
            * @type Number
            * @default 1
            */
            cfg.addProperty(DEF_CFG.MY_MONTH_POSITION.key, { value:DEF_CFG.MY_MONTH_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );

            /**
            * The position of the year in a month/year date string
            * @config MY_YEAR_POSITION
            * @type Number
            * @default 2
            */
            cfg.addProperty(DEF_CFG.MY_YEAR_POSITION.key, { value:DEF_CFG.MY_YEAR_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );

            /**
            * The position of the month in a month/day date string
            * @config MD_MONTH_POSITION
            * @type Number
            * @default 1
            */
            cfg.addProperty(DEF_CFG.MD_MONTH_POSITION.key, { value:DEF_CFG.MD_MONTH_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );

            /**
            * The position of the day in a month/year date string
            * @config MD_DAY_POSITION
            * @type Number
            * @default 2
            */
            cfg.addProperty(DEF_CFG.MD_DAY_POSITION.key,  { value:DEF_CFG.MD_DAY_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );

            /**
            * The position of the month in a month/day/year date string
            * @config MDY_MONTH_POSITION
            * @type Number
            * @default 1
            */
            cfg.addProperty(DEF_CFG.MDY_MONTH_POSITION.key, { value:DEF_CFG.MDY_MONTH_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );

            /**
            * The position of the day in a month/day/year date string
            * @config MDY_DAY_POSITION
            * @type Number
            * @default 2
            */
            cfg.addProperty(DEF_CFG.MDY_DAY_POSITION.key, { value:DEF_CFG.MDY_DAY_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );

            /**
            * The position of the year in a month/day/year date string
            * @config MDY_YEAR_POSITION
            * @type Number
            * @default 3
            */
            cfg.addProperty(DEF_CFG.MDY_YEAR_POSITION.key, { value:DEF_CFG.MDY_YEAR_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );

            /**
            * The position of the month in the month year label string used as the Calendar header
            * @config MY_LABEL_MONTH_POSITION
            * @type Number
            * @default 1
            */
            cfg.addProperty(DEF_CFG.MY_LABEL_MONTH_POSITION.key, { value:DEF_CFG.MY_LABEL_MONTH_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );

            /**
            * The position of the year in the month year label string used as the Calendar header
            * @config MY_LABEL_YEAR_POSITION
            * @type Number
            * @default 2
            */
            cfg.addProperty(DEF_CFG.MY_LABEL_YEAR_POSITION.key, { value:DEF_CFG.MY_LABEL_YEAR_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );

            /**
            * The suffix used after the month when rendering the Calendar header
            * @config MY_LABEL_MONTH_SUFFIX
            * @type String
            * @default " "
            */
            cfg.addProperty(DEF_CFG.MY_LABEL_MONTH_SUFFIX.key, { value:DEF_CFG.MY_LABEL_MONTH_SUFFIX.value, handler:this.delegateConfig } );

            /**
            * The suffix used after the year when rendering the Calendar header
            * @config MY_LABEL_YEAR_SUFFIX
            * @type String
            * @default ""
            */
            cfg.addProperty(DEF_CFG.MY_LABEL_YEAR_SUFFIX.key, { value:DEF_CFG.MY_LABEL_YEAR_SUFFIX.value, handler:this.delegateConfig } );

            /**
            * Configuration for the Month Year Navigation UI. By default it is disabled
            * @config NAV
            * @type Object
            * @default null
            */
            cfg.addProperty(DEF_CFG.NAV.key, { value:DEF_CFG.NAV.value, handler:this.configNavigator } );

            /**
             * The map of UI strings which the CalendarGroup UI uses.
             *
             * @config strings
             * @type {Object}
             * @default An object with the properties shown below:
             *     <dl>
             *         <dt>previousMonth</dt><dd><em>String</em> : The string to use for the "Previous Month" navigation UI. Defaults to "Previous Month".</dd>
             *         <dt>nextMonth</dt><dd><em>String</em> : The string to use for the "Next Month" navigation UI. Defaults to "Next Month".</dd>
             *         <dt>close</dt><dd><em>String</em> : The string to use for the close button label. Defaults to "Close".</dd>
             *     </dl>
             */
            cfg.addProperty(DEF_CFG.STRINGS.key, {
                value:DEF_CFG.STRINGS.value,
                handler:this.configStrings,
                validator: function(val) {
                    return Lang.isObject(val);
                },
                supercedes: DEF_CFG.STRINGS.supercedes
            });
        },

        /**
        * Initializes CalendarGroup's built-in CustomEvents
        * @method initEvents
        */
        initEvents : function() {

            var me = this,
                strEvent = "Event",
                CE = YAHOO.util.CustomEvent;

            /**
            * Proxy subscriber to subscribe to the CalendarGroup's child Calendars' CustomEvents
            * @method sub
            * @private
            * @param {Function} fn The function to subscribe to this CustomEvent
            * @param {Object} obj The CustomEvent's scope object
            * @param {Boolean} bOverride Whether or not to apply scope correction
            */
            var sub = function(fn, obj, bOverride) {
                for (var p=0;p<me.pages.length;++p) {
                    var cal = me.pages[p];
                    cal[this.type + strEvent].subscribe(fn, obj, bOverride);
                }
            };

            /**
            * Proxy unsubscriber to unsubscribe from the CalendarGroup's child Calendars' CustomEvents
            * @method unsub
            * @private
            * @param {Function} fn The function to subscribe to this CustomEvent
            * @param {Object} obj The CustomEvent's scope object
            */
            var unsub = function(fn, obj) {
                for (var p=0;p<me.pages.length;++p) {
                    var cal = me.pages[p];
                    cal[this.type + strEvent].unsubscribe(fn, obj);
                }
            };

            var defEvents = Calendar._EVENT_TYPES;

            /**
            * Fired before a date selection is made
            * @event beforeSelectEvent
            */
            me.beforeSelectEvent = new CE(defEvents.BEFORE_SELECT);
            me.beforeSelectEvent.subscribe = sub; me.beforeSelectEvent.unsubscribe = unsub;

            /**
            * Fired when a date selection is made
            * @event selectEvent
            * @param {Array} Array of Date field arrays in the format [YYYY, MM, DD].
            */
            me.selectEvent = new CE(defEvents.SELECT);
            me.selectEvent.subscribe = sub; me.selectEvent.unsubscribe = unsub;

            /**
            * Fired before a date or set of dates is deselected
            * @event beforeDeselectEvent
            */
            me.beforeDeselectEvent = new CE(defEvents.BEFORE_DESELECT);
            me.beforeDeselectEvent.subscribe = sub; me.beforeDeselectEvent.unsubscribe = unsub;

            /**
            * Fired when a date or set of dates has been deselected
            * @event deselectEvent
            * @param {Array} Array of Date field arrays in the format [YYYY, MM, DD].
            */
            me.deselectEvent = new CE(defEvents.DESELECT);
            me.deselectEvent.subscribe = sub; me.deselectEvent.unsubscribe = unsub;

            /**
            * Fired when the Calendar page is changed
            * @event changePageEvent
            */
            me.changePageEvent = new CE(defEvents.CHANGE_PAGE);
            me.changePageEvent.subscribe = sub; me.changePageEvent.unsubscribe = unsub;

            /**
            * Fired before the Calendar is rendered
            * @event beforeRenderEvent
            */
            me.beforeRenderEvent = new CE(defEvents.BEFORE_RENDER);
            me.beforeRenderEvent.subscribe = sub; me.beforeRenderEvent.unsubscribe = unsub;

            /**
            * Fired when the Calendar is rendered
            * @event renderEvent
            */
            me.renderEvent = new CE(defEvents.RENDER);
            me.renderEvent.subscribe = sub; me.renderEvent.unsubscribe = unsub;

            /**
            * Fired when the Calendar is reset
            * @event resetEvent
            */
            me.resetEvent = new CE(defEvents.RESET);
            me.resetEvent.subscribe = sub; me.resetEvent.unsubscribe = unsub;

            /**
            * Fired when the Calendar is cleared
            * @event clearEvent
            */
            me.clearEvent = new CE(defEvents.CLEAR);
            me.clearEvent.subscribe = sub; me.clearEvent.unsubscribe = unsub;

            /**
            * Fired just before the CalendarGroup is to be shown
            * @event beforeShowEvent
            */
            me.beforeShowEvent = new CE(defEvents.BEFORE_SHOW);

            /**
            * Fired after the CalendarGroup is shown
            * @event showEvent
            */
            me.showEvent = new CE(defEvents.SHOW);

            /**
            * Fired just before the CalendarGroup is to be hidden
            * @event beforeHideEvent
            */
            me.beforeHideEvent = new CE(defEvents.BEFORE_HIDE);

            /**
            * Fired after the CalendarGroup is hidden
            * @event hideEvent
            */
            me.hideEvent = new CE(defEvents.HIDE);

            /**
            * Fired just before the CalendarNavigator is to be shown
            * @event beforeShowNavEvent
            */
            me.beforeShowNavEvent = new CE(defEvents.BEFORE_SHOW_NAV);

            /**
            * Fired after the CalendarNavigator is shown
            * @event showNavEvent
            */
            me.showNavEvent = new CE(defEvents.SHOW_NAV);

            /**
            * Fired just before the CalendarNavigator is to be hidden
            * @event beforeHideNavEvent
            */
            me.beforeHideNavEvent = new CE(defEvents.BEFORE_HIDE_NAV);

            /**
            * Fired after the CalendarNavigator is hidden
            * @event hideNavEvent
            */
            me.hideNavEvent = new CE(defEvents.HIDE_NAV);

            /**
            * Fired just before the CalendarNavigator is to be rendered
            * @event beforeRenderNavEvent
            */
            me.beforeRenderNavEvent = new CE(defEvents.BEFORE_RENDER_NAV);

            /**
            * Fired after the CalendarNavigator is rendered
            * @event renderNavEvent
            */
            me.renderNavEvent = new CE(defEvents.RENDER_NAV);

            /**
            * Fired just before the CalendarGroup is to be destroyed
            * @event beforeDestroyEvent
            */
            me.beforeDestroyEvent = new CE(defEvents.BEFORE_DESTROY);

            /**
            * Fired after the CalendarGroup is destroyed. This event should be used
            * for notification only. When this event is fired, important CalendarGroup instance
            * properties, dom references and event listeners have already been
            * removed/dereferenced, and hence the CalendarGroup instance is not in a usable
            * state.
            *
            * @event destroyEvent
            */
            me.destroyEvent = new CE(defEvents.DESTROY);
        },

        /**
        * The default Config handler for the "pages" property
        * @method configPages
        * @param {String} type The CustomEvent type (usually the property name)
        * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
        * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
        */
        configPages : function(type, args, obj) {
            var pageCount = args[0],
                cfgPageDate = DEF_CFG.PAGEDATE.key,
                sep = "_",
                caldate,
                firstPageDate = null,
                groupCalClass = "groupcal",
                firstClass = "first-of-type",
                lastClass = "last-of-type";

            for (var p=0;p<pageCount;++p) {
                var calId = this.id + sep + p,
                    calContainerId = this.containerId + sep + p,
                    childConfig = this.cfg.getConfig();

                childConfig.close = false;
                childConfig.title = false;
                childConfig.navigator = null;

                if (p > 0) {
                    caldate = new Date(firstPageDate);
                    this._setMonthOnDate(caldate, caldate.getMonth() + p);
                    childConfig.pageDate = caldate;
                }

                var cal = this.constructChild(calId, calContainerId, childConfig);

                Dom.removeClass(cal.oDomContainer, this.Style.CSS_SINGLE);
                Dom.addClass(cal.oDomContainer, groupCalClass);

                if (p===0) {
                    firstPageDate = cal.cfg.getProperty(cfgPageDate);
                    Dom.addClass(cal.oDomContainer, firstClass);
                }

                if (p==(pageCount-1)) {
                    Dom.addClass(cal.oDomContainer, lastClass);
                }

                cal.parent = this;
                cal.index = p;

                this.pages[this.pages.length] = cal;
            }
        },

        /**
        * The default Config handler for the "pagedate" property
        * @method configPageDate
        * @param {String} type The CustomEvent type (usually the property name)
        * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
        * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
        */
        configPageDate : function(type, args, obj) {
            var val = args[0],
                firstPageDate;

            var cfgPageDate = DEF_CFG.PAGEDATE.key;

            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                if (p === 0) {
                    firstPageDate = cal._parsePageDate(val);
                    cal.cfg.setProperty(cfgPageDate, firstPageDate);
                } else {
                    var pageDate = new Date(firstPageDate);
                    this._setMonthOnDate(pageDate, pageDate.getMonth() + p);
                    cal.cfg.setProperty(cfgPageDate, pageDate);
                }
            }
        },

        /**
        * The default Config handler for the CalendarGroup "selected" property
        * @method configSelected
        * @param {String} type The CustomEvent type (usually the property name)
        * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
        * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
        */
        configSelected : function(type, args, obj) {
            var cfgSelected = DEF_CFG.SELECTED.key;
            this.delegateConfig(type, args, obj);
            var selected = (this.pages.length > 0) ? this.pages[0].cfg.getProperty(cfgSelected) : [];
            this.cfg.setProperty(cfgSelected, selected, true);
        },

        /**
        * Delegates a configuration property to the CustomEvents associated with the CalendarGroup's children
        * @method delegateConfig
        * @param {String} type The CustomEvent type (usually the property name)
        * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
        * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
        */
        delegateConfig : function(type, args, obj) {
            var val = args[0];
            var cal;

            for (var p=0;p<this.pages.length;p++) {
                cal = this.pages[p];
                cal.cfg.setProperty(type, val);
            }
        },

        /**
        * Adds a function to all child Calendars within this CalendarGroup.
        * @method setChildFunction
        * @param {String}  fnName  The name of the function
        * @param {Function}  fn   The function to apply to each Calendar page object
        */
        setChildFunction : function(fnName, fn) {
            var pageCount = this.cfg.getProperty(DEF_CFG.PAGES.key);

            for (var p=0;p<pageCount;++p) {
                this.pages[p][fnName] = fn;
            }
        },

        /**
        * Calls a function within all child Calendars within this CalendarGroup.
        * @method callChildFunction
        * @param {String}  fnName  The name of the function
        * @param {Array}  args  The arguments to pass to the function
        */
        callChildFunction : function(fnName, args) {
            var pageCount = this.cfg.getProperty(DEF_CFG.PAGES.key);

            for (var p=0;p<pageCount;++p) {
                var page = this.pages[p];
                if (page[fnName]) {
                    var fn = page[fnName];
                    fn.call(page, args);
                }
            }
        },

        /**
        * Constructs a child calendar. This method can be overridden if a subclassed version of the default
        * calendar is to be used.
        * @method constructChild
        * @param {String} id   The id of the table element that will represent the calendar widget
        * @param {String} containerId The id of the container div element that will wrap the calendar table
        * @param {Object} config  The configuration object containing the Calendar's arguments
        * @return {YAHOO.widget.Calendar} The YAHOO.widget.Calendar instance that is constructed
        */
        constructChild : function(id,containerId,config) {
            var container = document.getElementById(containerId);
            if (! container) {
                container = document.createElement("div");
                container.id = containerId;
                this.oDomContainer.appendChild(container);
            }
            return new Calendar(id,containerId,config);
        },

        /**
        * Sets the calendar group's month explicitly. This month will be set into the first
        * page of the multi-page calendar, and all other months will be iterated appropriately.
        * @method setMonth
        * @param {Number} month  The numeric month, from 0 (January) to 11 (December)
        */
        setMonth : function(month) {
            month = parseInt(month, 10);
            var currYear;

            var cfgPageDate = DEF_CFG.PAGEDATE.key;

            for (var p=0; p<this.pages.length; ++p) {
                var cal = this.pages[p];
                var pageDate = cal.cfg.getProperty(cfgPageDate);
                if (p === 0) {
                    currYear = pageDate.getFullYear();
                } else {
                    pageDate.setFullYear(currYear);
                }
                this._setMonthOnDate(pageDate, month+p);
                cal.cfg.setProperty(cfgPageDate, pageDate);
            }
        },

        /**
        * Sets the calendar group's year explicitly. This year will be set into the first
        * page of the multi-page calendar, and all other months will be iterated appropriately.
        * @method setYear
        * @param {Number} year  The numeric 4-digit year
        */
        setYear : function(year) {

            var cfgPageDate = DEF_CFG.PAGEDATE.key;

            year = parseInt(year, 10);
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                var pageDate = cal.cfg.getProperty(cfgPageDate);

                if ((pageDate.getMonth()+1) == 1 && p>0) {
                    year+=1;
                }
                cal.setYear(year);
            }
        },

        /**
        * Calls the render function of all child calendars within the group.
        * @method render
        */
        render : function() {
            this.renderHeader();
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.render();
            }
            this.renderFooter();
        },

        /**
        * Selects a date or a collection of dates on the current calendar. This method, by default,
        * does not call the render method explicitly. Once selection has completed, render must be
        * called for the changes to be reflected visually.
        * @method select
        * @param    {String/Date/Date[]}    date    The date string of dates to select in the current calendar. Valid formats are
        *                               individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006).
        *                               Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005).
        *                               This method can also take a JavaScript Date object or an array of Date objects.
        * @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected.
        */
        select : function(date) {
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.select(date);
            }
            return this.getSelectedDates();
        },

        /**
        * Selects dates in the CalendarGroup based on the cell index provided. This method is used to select cells without having to do a full render. The selected style is applied to the cells directly.
        * The value of the MULTI_SELECT Configuration attribute will determine the set of dates which get selected.
        * <ul>
        *    <li>If MULTI_SELECT is false, selectCell will select the cell at the specified index for only the last displayed Calendar page.</li>
        *    <li>If MULTI_SELECT is true, selectCell will select the cell at the specified index, on each displayed Calendar page.</li>
        * </ul>
        * @method selectCell
        * @param {Number} cellIndex The index of the cell to be selected.
        * @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected.
        */
        selectCell : function(cellIndex) {
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.selectCell(cellIndex);
            }
            return this.getSelectedDates();
        },

        /**
        * Deselects a date or a collection of dates on the current calendar. This method, by default,
        * does not call the render method explicitly. Once deselection has completed, render must be
        * called for the changes to be reflected visually.
        * @method deselect
        * @param {String/Date/Date[]} date The date string of dates to deselect in the current calendar. Valid formats are
        *        individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006).
        *        Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005).
        *        This method can also take a JavaScript Date object or an array of Date objects.
        * @return {Date[]}   Array of JavaScript Date objects representing all individual dates that are currently selected.
        */
        deselect : function(date) {
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.deselect(date);
            }
            return this.getSelectedDates();
        },

        /**
        * Deselects all dates on the current calendar.
        * @method deselectAll
        * @return {Date[]}  Array of JavaScript Date objects representing all individual dates that are currently selected.
        *      Assuming that this function executes properly, the return value should be an empty array.
        *      However, the empty array is returned for the sake of being able to check the selection status
        *      of the calendar.
        */
        deselectAll : function() {
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.deselectAll();
            }
            return this.getSelectedDates();
        },

        /**
        * Deselects dates in the CalendarGroup based on the cell index provided. This method is used to select cells without having to do a full render. The selected style is applied to the cells directly.
        * deselectCell will deselect the cell at the specified index on each displayed Calendar page.
        *
        * @method deselectCell
        * @param {Number} cellIndex The index of the cell to deselect.
        * @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected.
        */
        deselectCell : function(cellIndex) {
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.deselectCell(cellIndex);
            }
            return this.getSelectedDates();
        },

        /**
        * Resets the calendar widget to the originally selected month and year, and
        * sets the calendar to the initial selection(s).
        * @method reset
        */
        reset : function() {
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.reset();
            }
        },

        /**
        * Clears the selected dates in the current calendar widget and sets the calendar
        * to the current month and year.
        * @method clear
        */
        clear : function() {
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.clear();
            }

            this.cfg.setProperty(DEF_CFG.SELECTED.key, []);
            this.cfg.setProperty(DEF_CFG.PAGEDATE.key, new Date(this.pages[0].today.getTime()));
            this.render();
        },

        /**
        * Navigates to the next month page in the calendar widget.
        * @method nextMonth
        */
        nextMonth : function() {
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.nextMonth();
            }
        },

        /**
        * Navigates to the previous month page in the calendar widget.
        * @method previousMonth
        */
        previousMonth : function() {
            for (var p=this.pages.length-1;p>=0;--p) {
                var cal = this.pages[p];
                cal.previousMonth();
            }
        },

        /**
        * Navigates to the next year in the currently selected month in the calendar widget.
        * @method nextYear
        */
        nextYear : function() {
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.nextYear();
            }
        },

        /**
        * Navigates to the previous year in the currently selected month in the calendar widget.
        * @method previousYear
        */
        previousYear : function() {
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.previousYear();
            }
        },

        /**
        * Gets the list of currently selected dates from the calendar.
        * @return   An array of currently selected JavaScript Date objects.
        * @type Date[]
        */
        getSelectedDates : function() {
            var returnDates = [];
            var selected = this.cfg.getProperty(DEF_CFG.SELECTED.key);
            for (var d=0;d<selected.length;++d) {
                var dateArray = selected[d];

                var date = DateMath.getDate(dateArray[0],dateArray[1]-1,dateArray[2]);
                returnDates.push(date);
            }

            returnDates.sort( function(a,b) { return a-b; } );
            return returnDates;
        },

        /**
        * Adds a renderer to the render stack. The function reference passed to this method will be executed
        * when a date cell matches the conditions specified in the date string for this renderer.
        * @method addRenderer
        * @param {String} sDates  A date string to associate with the specified renderer. Valid formats
        *         include date (12/24/2005), month/day (12/24), and range (12/1/2004-1/1/2005)
        * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer.
        */
        addRenderer : function(sDates, fnRender) {
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.addRenderer(sDates, fnRender);
            }
        },

        /**
        * Adds a month to the render stack. The function reference passed to this method will be executed
        * when a date cell matches the month passed to this method.
        * @method addMonthRenderer
        * @param {Number} month  The month (1-12) to associate with this renderer
        * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer.
        */
        addMonthRenderer : function(month, fnRender) {
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.addMonthRenderer(month, fnRender);
            }
        },

        /**
        * Adds a weekday to the render stack. The function reference passed to this method will be executed
        * when a date cell matches the weekday passed to this method.
        * @method addWeekdayRenderer
        * @param {Number} weekday  The weekday (1-7) to associate with this renderer. 1=Sunday, 2=Monday etc.
        * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer.
        */
        addWeekdayRenderer : function(weekday, fnRender) {
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                cal.addWeekdayRenderer(weekday, fnRender);
            }
        },

        /**
         * Removes all custom renderers added to the CalendarGroup through the addRenderer, addMonthRenderer and
         * addWeekRenderer methods. CalendarGroup's render method needs to be called to after removing renderers
         * to see the changes applied.
         *
         * @method removeRenderers
         */
        removeRenderers : function() {
            this.callChildFunction("removeRenderers");
        },

        /**
        * Renders the header for the CalendarGroup.
        * @method renderHeader
        */
        renderHeader : function() {
            // EMPTY DEFAULT IMPL
        },

        /**
        * Renders a footer for the 2-up calendar container. By default, this method is
        * unimplemented.
        * @method renderFooter
        */
        renderFooter : function() {
            // EMPTY DEFAULT IMPL
        },

        /**
        * Adds the designated number of months to the current calendar month, and sets the current
        * calendar page date to the new month.
        * @method addMonths
        * @param {Number} count The number of months to add to the current calendar
        */
        addMonths : function(count) {
            this.callChildFunction("addMonths", count);
        },

        /**
        * Subtracts the designated number of months from the current calendar month, and sets the current
        * calendar page date to the new month.
        * @method subtractMonths
        * @param {Number} count The number of months to subtract from the current calendar
        */
        subtractMonths : function(count) {
            this.callChildFunction("subtractMonths", count);
        },

        /**
        * Adds the designated number of years to the current calendar, and sets the current
        * calendar page date to the new month.
        * @method addYears
        * @param {Number} count The number of years to add to the current calendar
        */
        addYears : function(count) {
            this.callChildFunction("addYears", count);
        },

        /**
        * Subtcats the designated number of years from the current calendar, and sets the current
        * calendar page date to the new month.
        * @method subtractYears
        * @param {Number} count The number of years to subtract from the current calendar
        */
        subtractYears : function(count) {
            this.callChildFunction("subtractYears", count);
        },

        /**
         * Returns the Calendar page instance which has a pagedate (month/year) matching the given date.
         * Returns null if no match is found.
         *
         * @method getCalendarPage
         * @param {Date} date The JavaScript Date object for which a Calendar page is to be found.
         * @return {Calendar} The Calendar page instance representing the month to which the date
         * belongs.
         */
        getCalendarPage : function(date) {
            var cal = null;
            if (date) {
                var y = date.getFullYear(),
                    m = date.getMonth();

                var pages = this.pages;
                for (var i = 0; i < pages.length; ++i) {
                    var pageDate = pages[i].cfg.getProperty("pagedate");
                    if (pageDate.getFullYear() === y && pageDate.getMonth() === m) {
                        cal = pages[i];
                        break;
                    }
                }
            }
            return cal;
        },

        /**
        * Sets the month on a Date object, taking into account year rollover if the month is less than 0 or greater than 11.
        * The Date object passed in is modified. It should be cloned before passing it into this method if the original value needs to be maintained
        * @method _setMonthOnDate
        * @private
        * @param {Date} date The Date object on which to set the month index
        * @param {Number} iMonth The month index to set
        */
        _setMonthOnDate : function(date, iMonth) {
            // Bug in Safari 1.3, 2.0 (WebKit build < 420), Date.setMonth does not work consistently if iMonth is not 0-11
            if (YAHOO.env.ua.webkit && YAHOO.env.ua.webkit < 420 && (iMonth < 0 || iMonth > 11)) {
                var newDate = DateMath.add(date, DateMath.MONTH, iMonth-date.getMonth());
                date.setTime(newDate.getTime());
            } else {
                date.setMonth(iMonth);
            }
        },

        /**
         * Fixes the width of the CalendarGroup container element, to account for miswrapped floats
         * @method _fixWidth
         * @private
         */
        _fixWidth : function() {
            var w = 0;
            for (var p=0;p<this.pages.length;++p) {
                var cal = this.pages[p];
                w += cal.oDomContainer.offsetWidth;
            }
            if (w > 0) {
                this.oDomContainer.style.width = w + "px";
            }
        },

        /**
        * Returns a string representation of the object.
        * @method toString
        * @return {String} A string representation of the CalendarGroup object.
        */
        toString : function() {
            return "CalendarGroup " + this.id;
        },

        /**
         * Destroys the CalendarGroup instance. The method will remove references
         * to HTML elements, remove any event listeners added by the CalendarGroup.
         *
         * It will also destroy the Config and CalendarNavigator instances created by the
         * CalendarGroup and the individual Calendar instances created for each page.
         *
         * @method destroy
         */
        destroy : function() {

            if (this.beforeDestroyEvent.fire()) {

                var cal = this;

                // Child objects
                if (cal.navigator) {
                    cal.navigator.destroy();
                }

                if (cal.cfg) {
                    cal.cfg.destroy();
                }

                // DOM event listeners
                Event.purgeElement(cal.oDomContainer, true);

                // Generated markup/DOM - Not removing the container DIV since we didn't create it.
                Dom.removeClass(cal.oDomContainer, CalendarGroup.CSS_CONTAINER);
                Dom.removeClass(cal.oDomContainer, CalendarGroup.CSS_MULTI_UP);

                for (var i = 0, l = cal.pages.length; i < l; i++) {
                    cal.pages[i].destroy();
                    cal.pages[i] = null;
                }

                cal.oDomContainer.innerHTML = "";

                // JS-to-DOM references
                cal.oDomContainer = null;

                this.destroyEvent.fire();
            }
        }
    };

    /**
    * CSS class representing the container for the calendar
    * @property YAHOO.widget.CalendarGroup.CSS_CONTAINER
    * @static
    * @final
    * @type String
    */
    CalendarGroup.CSS_CONTAINER = "yui-calcontainer";

    /**
    * CSS class representing the container for the calendar
    * @property YAHOO.widget.CalendarGroup.CSS_MULTI_UP
    * @static
    * @final
    * @type String
    */
    CalendarGroup.CSS_MULTI_UP = "multi";

    /**
    * CSS class representing the title for the 2-up calendar
    * @property YAHOO.widget.CalendarGroup.CSS_2UPTITLE
    * @static
    * @final
    * @type String
    */
    CalendarGroup.CSS_2UPTITLE = "title";

    /**
    * CSS class representing the close icon for the 2-up calendar
    * @property YAHOO.widget.CalendarGroup.CSS_2UPCLOSE
    * @static
    * @final
    * @deprecated Along with Calendar.IMG_ROOT and NAV_ARROW_LEFT, NAV_ARROW_RIGHT configuration properties.
    *     Calendar's <a href="YAHOO.widget.Calendar.html#Style.CSS_CLOSE">Style.CSS_CLOSE</a> property now represents the CSS class used to render the close icon
    * @type String
    */
    CalendarGroup.CSS_2UPCLOSE = "close-icon";

    YAHOO.lang.augmentProto(CalendarGroup, Calendar, "buildDayLabel",
                                                     "buildMonthLabel",
                                                     "renderOutOfBoundsDate",
                                                     "renderRowHeader",
                                                     "renderRowFooter",
                                                     "renderCellDefault",
                                                     "styleCellDefault",
                                                     "renderCellStyleHighlight1",
                                                     "renderCellStyleHighlight2",
                                                     "renderCellStyleHighlight3",
                                                     "renderCellStyleHighlight4",
                                                     "renderCellStyleToday",
                                                     "renderCellStyleSelected",
                                                     "renderCellNotThisMonth",
                                                     "renderBodyCellRestricted",
                                                     "initStyles",
                                                     "configTitle",
                                                     "configClose",
                                                     "configIframe",
                                                     "configStrings",
                                                     "configToday",
                                                     "configNavigator",
                                                     "createTitleBar",
                                                     "createCloseButton",
                                                     "removeTitleBar",
                                                     "removeCloseButton",
                                                     "hide",
                                                     "show",
                                                     "toDate",
                                                     "_toDate",
                                                     "_parseArgs",
                                                     "browser");

    YAHOO.widget.CalGrp = CalendarGroup;
    YAHOO.widget.CalendarGroup = CalendarGroup;

    /**
    * @class YAHOO.widget.Calendar2up
    * @extends YAHOO.widget.CalendarGroup
    * @deprecated The old Calendar2up class is no longer necessary, since CalendarGroup renders in a 2up view by default.
    */
    YAHOO.widget.Calendar2up = function(id, containerId, config) {
        this.init(id, containerId, config);
    };

    YAHOO.extend(YAHOO.widget.Calendar2up, CalendarGroup);

    /**
    * @deprecated The old Calendar2up class is no longer necessary, since CalendarGroup renders in a 2up view by default.
    */
    YAHOO.widget.Cal2up = YAHOO.widget.Calendar2up;

    })();

Copyright © 2009 Yahoo! Inc. All rights reserved.