# Yahoo! UI Library

### Calendar 2.7.0

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
    * @property YAHOO.widget.CalendarGroup._DEFAULT_CONFIG
    * @final
    * @static
    * @private
    * @type Object
    */
    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 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:new Date(), 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",
    												 "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.