|  | /* | 
|  | Copyright (c) 2008, Yahoo! Inc. All rights reserved. | 
|  | Code licensed under the BSD License: | 
|  | http://developer.yahoo.net/yui/license.txt | 
|  | version: 2.6.0 | 
|  | */ | 
|  | (function () { | 
|  |  | 
|  | /** | 
|  | * Config is a utility used within an Object to allow the implementer to | 
|  | * maintain a list of local configuration properties and listen for changes | 
|  | * to those properties dynamically using CustomEvent. The initial values are | 
|  | * also maintained so that the configuration can be reset at any given point | 
|  | * to its initial state. | 
|  | * @namespace YAHOO.util | 
|  | * @class Config | 
|  | * @constructor | 
|  | * @param {Object} owner The owner Object to which this Config Object belongs | 
|  | */ | 
|  | YAHOO.util.Config = function (owner) { | 
|  |  | 
|  | if (owner) { | 
|  | this.init(owner); | 
|  | } | 
|  |  | 
|  |  | 
|  | }; | 
|  |  | 
|  |  | 
|  | var Lang = YAHOO.lang, | 
|  | CustomEvent = YAHOO.util.CustomEvent, | 
|  | Config = YAHOO.util.Config; | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Constant representing the CustomEvent type for the config changed event. | 
|  | * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT | 
|  | * @private | 
|  | * @static | 
|  | * @final | 
|  | */ | 
|  | Config.CONFIG_CHANGED_EVENT = "configChanged"; | 
|  |  | 
|  | /** | 
|  | * Constant representing the boolean type string | 
|  | * @property YAHOO.util.Config.BOOLEAN_TYPE | 
|  | * @private | 
|  | * @static | 
|  | * @final | 
|  | */ | 
|  | Config.BOOLEAN_TYPE = "boolean"; | 
|  |  | 
|  | Config.prototype = { | 
|  |  | 
|  | /** | 
|  | * Object reference to the owner of this Config Object | 
|  | * @property owner | 
|  | * @type Object | 
|  | */ | 
|  | owner: null, | 
|  |  | 
|  | /** | 
|  | * Boolean flag that specifies whether a queue is currently | 
|  | * being executed | 
|  | * @property queueInProgress | 
|  | * @type Boolean | 
|  | */ | 
|  | queueInProgress: false, | 
|  |  | 
|  | /** | 
|  | * Maintains the local collection of configuration property objects and | 
|  | * their specified values | 
|  | * @property config | 
|  | * @private | 
|  | * @type Object | 
|  | */ | 
|  | config: null, | 
|  |  | 
|  | /** | 
|  | * Maintains the local collection of configuration property objects as | 
|  | * they were initially applied. | 
|  | * This object is used when resetting a property. | 
|  | * @property initialConfig | 
|  | * @private | 
|  | * @type Object | 
|  | */ | 
|  | initialConfig: null, | 
|  |  | 
|  | /** | 
|  | * Maintains the local, normalized CustomEvent queue | 
|  | * @property eventQueue | 
|  | * @private | 
|  | * @type Object | 
|  | */ | 
|  | eventQueue: null, | 
|  |  | 
|  | /** | 
|  | * Custom Event, notifying subscribers when Config properties are set | 
|  | * (setProperty is called without the silent flag | 
|  | * @event configChangedEvent | 
|  | */ | 
|  | configChangedEvent: null, | 
|  |  | 
|  | /** | 
|  | * Initializes the configuration Object and all of its local members. | 
|  | * @method init | 
|  | * @param {Object} owner The owner Object to which this Config | 
|  | * Object belongs | 
|  | */ | 
|  | init: function (owner) { | 
|  |  | 
|  | this.owner = owner; | 
|  |  | 
|  | this.configChangedEvent = | 
|  | this.createEvent(Config.CONFIG_CHANGED_EVENT); | 
|  |  | 
|  | this.configChangedEvent.signature = CustomEvent.LIST; | 
|  | this.queueInProgress = false; | 
|  | this.config = {}; | 
|  | this.initialConfig = {}; | 
|  | this.eventQueue = []; | 
|  |  | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Validates that the value passed in is a Boolean. | 
|  | * @method checkBoolean | 
|  | * @param {Object} val The value to validate | 
|  | * @return {Boolean} true, if the value is valid | 
|  | */ | 
|  | checkBoolean: function (val) { | 
|  | return (typeof val == Config.BOOLEAN_TYPE); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Validates that the value passed in is a number. | 
|  | * @method checkNumber | 
|  | * @param {Object} val The value to validate | 
|  | * @return {Boolean} true, if the value is valid | 
|  | */ | 
|  | checkNumber: function (val) { | 
|  | return (!isNaN(val)); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Fires a configuration property event using the specified value. | 
|  | * @method fireEvent | 
|  | * @private | 
|  | * @param {String} key The configuration property's name | 
|  | * @param {value} Object The value of the correct type for the property | 
|  | */ | 
|  | fireEvent: function ( key, value ) { | 
|  | var property = this.config[key]; | 
|  |  | 
|  | if (property && property.event) { | 
|  | property.event.fire(value); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Adds a property to the Config Object's private config hash. | 
|  | * @method addProperty | 
|  | * @param {String} key The configuration property's name | 
|  | * @param {Object} propertyObject The Object containing all of this | 
|  | * property's arguments | 
|  | */ | 
|  | addProperty: function ( key, propertyObject ) { | 
|  | key = key.toLowerCase(); | 
|  |  | 
|  | this.config[key] = propertyObject; | 
|  |  | 
|  | propertyObject.event = this.createEvent(key, { scope: this.owner }); | 
|  | propertyObject.event.signature = CustomEvent.LIST; | 
|  |  | 
|  |  | 
|  | propertyObject.key = key; | 
|  |  | 
|  | if (propertyObject.handler) { | 
|  | propertyObject.event.subscribe(propertyObject.handler, | 
|  | this.owner); | 
|  | } | 
|  |  | 
|  | this.setProperty(key, propertyObject.value, true); | 
|  |  | 
|  | if (! propertyObject.suppressEvent) { | 
|  | this.queueProperty(key, propertyObject.value); | 
|  | } | 
|  |  | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Returns a key-value configuration map of the values currently set in | 
|  | * the Config Object. | 
|  | * @method getConfig | 
|  | * @return {Object} The current config, represented in a key-value map | 
|  | */ | 
|  | getConfig: function () { | 
|  |  | 
|  | var cfg = {}, | 
|  | currCfg = this.config, | 
|  | prop, | 
|  | property; | 
|  |  | 
|  | for (prop in currCfg) { | 
|  | if (Lang.hasOwnProperty(currCfg, prop)) { | 
|  | property = currCfg[prop]; | 
|  | if (property && property.event) { | 
|  | cfg[prop] = property.value; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return cfg; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Returns the value of specified property. | 
|  | * @method getProperty | 
|  | * @param {String} key The name of the property | 
|  | * @return {Object}  The value of the specified property | 
|  | */ | 
|  | getProperty: function (key) { | 
|  | var property = this.config[key.toLowerCase()]; | 
|  | if (property && property.event) { | 
|  | return property.value; | 
|  | } else { | 
|  | return undefined; | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Resets the specified property's value to its initial value. | 
|  | * @method resetProperty | 
|  | * @param {String} key The name of the property | 
|  | * @return {Boolean} True is the property was reset, false if not | 
|  | */ | 
|  | resetProperty: function (key) { | 
|  |  | 
|  | key = key.toLowerCase(); | 
|  |  | 
|  | var property = this.config[key]; | 
|  |  | 
|  | if (property && property.event) { | 
|  |  | 
|  | if (this.initialConfig[key] && | 
|  | !Lang.isUndefined(this.initialConfig[key])) { | 
|  |  | 
|  | this.setProperty(key, this.initialConfig[key]); | 
|  |  | 
|  | return true; | 
|  |  | 
|  | } | 
|  |  | 
|  | } else { | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Sets the value of a property. If the silent property is passed as | 
|  | * true, the property's event will not be fired. | 
|  | * @method setProperty | 
|  | * @param {String} key The name of the property | 
|  | * @param {String} value The value to set the property to | 
|  | * @param {Boolean} silent Whether the value should be set silently, | 
|  | * without firing the property event. | 
|  | * @return {Boolean} True, if the set was successful, false if it failed. | 
|  | */ | 
|  | setProperty: function (key, value, silent) { | 
|  |  | 
|  | var property; | 
|  |  | 
|  | key = key.toLowerCase(); | 
|  |  | 
|  | if (this.queueInProgress && ! silent) { | 
|  | // Currently running through a queue... | 
|  | this.queueProperty(key,value); | 
|  | return true; | 
|  |  | 
|  | } else { | 
|  | property = this.config[key]; | 
|  | if (property && property.event) { | 
|  | if (property.validator && !property.validator(value)) { | 
|  | return false; | 
|  | } else { | 
|  | property.value = value; | 
|  | if (! silent) { | 
|  | this.fireEvent(key, value); | 
|  | this.configChangedEvent.fire([key, value]); | 
|  | } | 
|  | return true; | 
|  | } | 
|  | } else { | 
|  | return false; | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Sets the value of a property and queues its event to execute. If the | 
|  | * event is already scheduled to execute, it is | 
|  | * moved from its current position to the end of the queue. | 
|  | * @method queueProperty | 
|  | * @param {String} key The name of the property | 
|  | * @param {String} value The value to set the property to | 
|  | * @return {Boolean}  true, if the set was successful, false if | 
|  | * it failed. | 
|  | */ | 
|  | queueProperty: function (key, value) { | 
|  |  | 
|  | key = key.toLowerCase(); | 
|  |  | 
|  | var property = this.config[key], | 
|  | foundDuplicate = false, | 
|  | iLen, | 
|  | queueItem, | 
|  | queueItemKey, | 
|  | queueItemValue, | 
|  | sLen, | 
|  | supercedesCheck, | 
|  | qLen, | 
|  | queueItemCheck, | 
|  | queueItemCheckKey, | 
|  | queueItemCheckValue, | 
|  | i, | 
|  | s, | 
|  | q; | 
|  |  | 
|  | if (property && property.event) { | 
|  |  | 
|  | if (!Lang.isUndefined(value) && property.validator && | 
|  | !property.validator(value)) { // validator | 
|  | return false; | 
|  | } else { | 
|  |  | 
|  | if (!Lang.isUndefined(value)) { | 
|  | property.value = value; | 
|  | } else { | 
|  | value = property.value; | 
|  | } | 
|  |  | 
|  | foundDuplicate = false; | 
|  | iLen = this.eventQueue.length; | 
|  |  | 
|  | for (i = 0; i < iLen; i++) { | 
|  | queueItem = this.eventQueue[i]; | 
|  |  | 
|  | if (queueItem) { | 
|  | queueItemKey = queueItem[0]; | 
|  | queueItemValue = queueItem[1]; | 
|  |  | 
|  | if (queueItemKey == key) { | 
|  |  | 
|  | /* | 
|  | found a dupe... push to end of queue, null | 
|  | current item, and break | 
|  | */ | 
|  |  | 
|  | this.eventQueue[i] = null; | 
|  |  | 
|  | this.eventQueue.push( | 
|  | [key, (!Lang.isUndefined(value) ? | 
|  | value : queueItemValue)]); | 
|  |  | 
|  | foundDuplicate = true; | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // this is a refire, or a new property in the queue | 
|  |  | 
|  | if (! foundDuplicate && !Lang.isUndefined(value)) { | 
|  | this.eventQueue.push([key, value]); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (property.supercedes) { | 
|  |  | 
|  | sLen = property.supercedes.length; | 
|  |  | 
|  | for (s = 0; s < sLen; s++) { | 
|  |  | 
|  | supercedesCheck = property.supercedes[s]; | 
|  | qLen = this.eventQueue.length; | 
|  |  | 
|  | for (q = 0; q < qLen; q++) { | 
|  | queueItemCheck = this.eventQueue[q]; | 
|  |  | 
|  | if (queueItemCheck) { | 
|  | queueItemCheckKey = queueItemCheck[0]; | 
|  | queueItemCheckValue = queueItemCheck[1]; | 
|  |  | 
|  | if (queueItemCheckKey == | 
|  | supercedesCheck.toLowerCase() ) { | 
|  |  | 
|  | this.eventQueue.push([queueItemCheckKey, | 
|  | queueItemCheckValue]); | 
|  |  | 
|  | this.eventQueue[q] = null; | 
|  | break; | 
|  |  | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | return true; | 
|  | } else { | 
|  | return false; | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Fires the event for a property using the property's current value. | 
|  | * @method refireEvent | 
|  | * @param {String} key The name of the property | 
|  | */ | 
|  | refireEvent: function (key) { | 
|  |  | 
|  | key = key.toLowerCase(); | 
|  |  | 
|  | var property = this.config[key]; | 
|  |  | 
|  | if (property && property.event && | 
|  |  | 
|  | !Lang.isUndefined(property.value)) { | 
|  |  | 
|  | if (this.queueInProgress) { | 
|  |  | 
|  | this.queueProperty(key); | 
|  |  | 
|  | } else { | 
|  |  | 
|  | this.fireEvent(key, property.value); | 
|  |  | 
|  | } | 
|  |  | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Applies a key-value Object literal to the configuration, replacing | 
|  | * any existing values, and queueing the property events. | 
|  | * Although the values will be set, fireQueue() must be called for their | 
|  | * associated events to execute. | 
|  | * @method applyConfig | 
|  | * @param {Object} userConfig The configuration Object literal | 
|  | * @param {Boolean} init  When set to true, the initialConfig will | 
|  | * be set to the userConfig passed in, so that calling a reset will | 
|  | * reset the properties to the passed values. | 
|  | */ | 
|  | applyConfig: function (userConfig, init) { | 
|  |  | 
|  | var sKey, | 
|  | oConfig; | 
|  |  | 
|  | if (init) { | 
|  | oConfig = {}; | 
|  | for (sKey in userConfig) { | 
|  | if (Lang.hasOwnProperty(userConfig, sKey)) { | 
|  | oConfig[sKey.toLowerCase()] = userConfig[sKey]; | 
|  | } | 
|  | } | 
|  | this.initialConfig = oConfig; | 
|  | } | 
|  |  | 
|  | for (sKey in userConfig) { | 
|  | if (Lang.hasOwnProperty(userConfig, sKey)) { | 
|  | this.queueProperty(sKey, userConfig[sKey]); | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Refires the events for all configuration properties using their | 
|  | * current values. | 
|  | * @method refresh | 
|  | */ | 
|  | refresh: function () { | 
|  |  | 
|  | var prop; | 
|  |  | 
|  | for (prop in this.config) { | 
|  | if (Lang.hasOwnProperty(this.config, prop)) { | 
|  | this.refireEvent(prop); | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Fires the normalized list of queued property change events | 
|  | * @method fireQueue | 
|  | */ | 
|  | fireQueue: function () { | 
|  |  | 
|  | var i, | 
|  | queueItem, | 
|  | key, | 
|  | value, | 
|  | property; | 
|  |  | 
|  | this.queueInProgress = true; | 
|  | for (i = 0;i < this.eventQueue.length; i++) { | 
|  | queueItem = this.eventQueue[i]; | 
|  | if (queueItem) { | 
|  |  | 
|  | key = queueItem[0]; | 
|  | value = queueItem[1]; | 
|  | property = this.config[key]; | 
|  |  | 
|  | property.value = value; | 
|  |  | 
|  | this.fireEvent(key,value); | 
|  | } | 
|  | } | 
|  |  | 
|  | this.queueInProgress = false; | 
|  | this.eventQueue = []; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Subscribes an external handler to the change event for any | 
|  | * given property. | 
|  | * @method subscribeToConfigEvent | 
|  | * @param {String} key The property name | 
|  | * @param {Function} handler The handler function to use subscribe to | 
|  | * the property's event | 
|  | * @param {Object} obj The Object to use for scoping the event handler | 
|  | * (see CustomEvent documentation) | 
|  | * @param {Boolean} override Optional. If true, will override "this" | 
|  | * within the handler to map to the scope Object passed into the method. | 
|  | * @return {Boolean} True, if the subscription was successful, | 
|  | * otherwise false. | 
|  | */ | 
|  | subscribeToConfigEvent: function (key, handler, obj, override) { | 
|  |  | 
|  | var property = this.config[key.toLowerCase()]; | 
|  |  | 
|  | if (property && property.event) { | 
|  | if (!Config.alreadySubscribed(property.event, handler, obj)) { | 
|  | property.event.subscribe(handler, obj, override); | 
|  | } | 
|  | return true; | 
|  | } else { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Unsubscribes an external handler from the change event for any | 
|  | * given property. | 
|  | * @method unsubscribeFromConfigEvent | 
|  | * @param {String} key The property name | 
|  | * @param {Function} handler The handler function to use subscribe to | 
|  | * the property's event | 
|  | * @param {Object} obj The Object to use for scoping the event | 
|  | * handler (see CustomEvent documentation) | 
|  | * @return {Boolean} True, if the unsubscription was successful, | 
|  | * otherwise false. | 
|  | */ | 
|  | unsubscribeFromConfigEvent: function (key, handler, obj) { | 
|  | var property = this.config[key.toLowerCase()]; | 
|  | if (property && property.event) { | 
|  | return property.event.unsubscribe(handler, obj); | 
|  | } else { | 
|  | return false; | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Returns a string representation of the Config object | 
|  | * @method toString | 
|  | * @return {String} The Config object in string format. | 
|  | */ | 
|  | toString: function () { | 
|  | var output = "Config"; | 
|  | if (this.owner) { | 
|  | output += " [" + this.owner.toString() + "]"; | 
|  | } | 
|  | return output; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Returns a string representation of the Config object's current | 
|  | * CustomEvent queue | 
|  | * @method outputEventQueue | 
|  | * @return {String} The string list of CustomEvents currently queued | 
|  | * for execution | 
|  | */ | 
|  | outputEventQueue: function () { | 
|  |  | 
|  | var output = "", | 
|  | queueItem, | 
|  | q, | 
|  | nQueue = this.eventQueue.length; | 
|  |  | 
|  | for (q = 0; q < nQueue; q++) { | 
|  | queueItem = this.eventQueue[q]; | 
|  | if (queueItem) { | 
|  | output += queueItem[0] + "=" + queueItem[1] + ", "; | 
|  | } | 
|  | } | 
|  | return output; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Sets all properties to null, unsubscribes all listeners from each | 
|  | * property's change event and all listeners from the configChangedEvent. | 
|  | * @method destroy | 
|  | */ | 
|  | destroy: function () { | 
|  |  | 
|  | var oConfig = this.config, | 
|  | sProperty, | 
|  | oProperty; | 
|  |  | 
|  |  | 
|  | for (sProperty in oConfig) { | 
|  |  | 
|  | if (Lang.hasOwnProperty(oConfig, sProperty)) { | 
|  |  | 
|  | oProperty = oConfig[sProperty]; | 
|  |  | 
|  | oProperty.event.unsubscribeAll(); | 
|  | oProperty.event = null; | 
|  |  | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | this.configChangedEvent.unsubscribeAll(); | 
|  |  | 
|  | this.configChangedEvent = null; | 
|  | this.owner = null; | 
|  | this.config = null; | 
|  | this.initialConfig = null; | 
|  | this.eventQueue = null; | 
|  |  | 
|  | } | 
|  |  | 
|  | }; | 
|  |  | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Checks to determine if a particular function/Object pair are already | 
|  | * subscribed to the specified CustomEvent | 
|  | * @method YAHOO.util.Config.alreadySubscribed | 
|  | * @static | 
|  | * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check | 
|  | * the subscriptions | 
|  | * @param {Function} fn The function to look for in the subscribers list | 
|  | * @param {Object} obj The execution scope Object for the subscription | 
|  | * @return {Boolean} true, if the function/Object pair is already subscribed | 
|  | * to the CustomEvent passed in | 
|  | */ | 
|  | Config.alreadySubscribed = function (evt, fn, obj) { | 
|  |  | 
|  | var nSubscribers = evt.subscribers.length, | 
|  | subsc, | 
|  | i; | 
|  |  | 
|  | if (nSubscribers > 0) { | 
|  | i = nSubscribers - 1; | 
|  | do { | 
|  | subsc = evt.subscribers[i]; | 
|  | if (subsc && subsc.obj == obj && subsc.fn == fn) { | 
|  | return true; | 
|  | } | 
|  | } | 
|  | while (i--); | 
|  | } | 
|  |  | 
|  | return false; | 
|  |  | 
|  | }; | 
|  |  | 
|  | YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider); | 
|  |  | 
|  | }()); | 
|  |  | 
|  | /** | 
|  | * YAHOO.widget.DateMath is used for simple date manipulation. The class is a static utility | 
|  | * used for adding, subtracting, and comparing dates. | 
|  | * @namespace YAHOO.widget | 
|  | * @class DateMath | 
|  | */ | 
|  | YAHOO.widget.DateMath = { | 
|  | /** | 
|  | * Constant field representing Day | 
|  | * @property DAY | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | DAY : "D", | 
|  |  | 
|  | /** | 
|  | * Constant field representing Week | 
|  | * @property WEEK | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | WEEK : "W", | 
|  |  | 
|  | /** | 
|  | * Constant field representing Year | 
|  | * @property YEAR | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | YEAR : "Y", | 
|  |  | 
|  | /** | 
|  | * Constant field representing Month | 
|  | * @property MONTH | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | MONTH : "M", | 
|  |  | 
|  | /** | 
|  | * Constant field representing one day, in milliseconds | 
|  | * @property ONE_DAY_MS | 
|  | * @static | 
|  | * @final | 
|  | * @type Number | 
|  | */ | 
|  | ONE_DAY_MS : 1000*60*60*24, | 
|  |  | 
|  | /** | 
|  | * Constant field representing the date in first week of January | 
|  | * which identifies the first week of the year. | 
|  | * <p> | 
|  | * In the U.S, Jan 1st is normally used based on a Sunday start of week. | 
|  | * ISO 8601, used widely throughout Europe, uses Jan 4th, based on a Monday start of week. | 
|  | * </p> | 
|  | * @property WEEK_ONE_JAN_DATE | 
|  | * @static | 
|  | * @type Number | 
|  | */ | 
|  | WEEK_ONE_JAN_DATE : 1, | 
|  |  | 
|  | /** | 
|  | * Adds the specified amount of time to the this instance. | 
|  | * @method add | 
|  | * @param {Date} date	The JavaScript Date object to perform addition on | 
|  | * @param {String} field	The field constant to be used for performing addition. | 
|  | * @param {Number} amount	The number of units (measured in the field constant) to add to the date. | 
|  | * @return {Date} The resulting Date object | 
|  | */ | 
|  | add : function(date, field, amount) { | 
|  | var d = new Date(date.getTime()); | 
|  | switch (field) { | 
|  | case this.MONTH: | 
|  | var newMonth = date.getMonth() + amount; | 
|  | var years = 0; | 
|  |  | 
|  | if (newMonth < 0) { | 
|  | while (newMonth < 0) { | 
|  | newMonth += 12; | 
|  | years -= 1; | 
|  | } | 
|  | } else if (newMonth > 11) { | 
|  | while (newMonth > 11) { | 
|  | newMonth -= 12; | 
|  | years += 1; | 
|  | } | 
|  | } | 
|  |  | 
|  | d.setMonth(newMonth); | 
|  | d.setFullYear(date.getFullYear() + years); | 
|  | break; | 
|  | case this.DAY: | 
|  | this._addDays(d, amount); | 
|  | // d.setDate(date.getDate() + amount); | 
|  | break; | 
|  | case this.YEAR: | 
|  | d.setFullYear(date.getFullYear() + amount); | 
|  | break; | 
|  | case this.WEEK: | 
|  | this._addDays(d, (amount * 7)); | 
|  | // d.setDate(date.getDate() + (amount * 7)); | 
|  | break; | 
|  | } | 
|  | return d; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Private helper method to account for bug in Safari 2 (webkit < 420) | 
|  | * when Date.setDate(n) is called with n less than -128 or greater than 127. | 
|  | * <p> | 
|  | * Fix approach and original findings are available here: | 
|  | * http://brianary.blogspot.com/2006/03/safari-date-bug.html | 
|  | * </p> | 
|  | * @method _addDays | 
|  | * @param {Date} d JavaScript date object | 
|  | * @param {Number} nDays The number of days to add to the date object (can be negative) | 
|  | * @private | 
|  | */ | 
|  | _addDays : function(d, nDays) { | 
|  | if (YAHOO.env.ua.webkit && YAHOO.env.ua.webkit < 420) { | 
|  | if (nDays < 0) { | 
|  | // Ensure we don't go below -128 (getDate() is always 1 to 31, so we won't go above 127) | 
|  | for(var min = -128; nDays < min; nDays -= min) { | 
|  | d.setDate(d.getDate() + min); | 
|  | } | 
|  | } else { | 
|  | // Ensure we don't go above 96 + 31 = 127 | 
|  | for(var max = 96; nDays > max; nDays -= max) { | 
|  | d.setDate(d.getDate() + max); | 
|  | } | 
|  | } | 
|  | // nDays should be remainder between -128 and 96 | 
|  | } | 
|  | d.setDate(d.getDate() + nDays); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Subtracts the specified amount of time from the this instance. | 
|  | * @method subtract | 
|  | * @param {Date} date	The JavaScript Date object to perform subtraction on | 
|  | * @param {Number} field	The this field constant to be used for performing subtraction. | 
|  | * @param {Number} amount	The number of units (measured in the field constant) to subtract from the date. | 
|  | * @return {Date} The resulting Date object | 
|  | */ | 
|  | subtract : function(date, field, amount) { | 
|  | return this.add(date, field, (amount*-1)); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Determines whether a given date is before another date on the calendar. | 
|  | * @method before | 
|  | * @param {Date} date		The Date object to compare with the compare argument | 
|  | * @param {Date} compareTo	The Date object to use for the comparison | 
|  | * @return {Boolean} true if the date occurs before the compared date; false if not. | 
|  | */ | 
|  | before : function(date, compareTo) { | 
|  | var ms = compareTo.getTime(); | 
|  | if (date.getTime() < ms) { | 
|  | return true; | 
|  | } else { | 
|  | return false; | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Determines whether a given date is after another date on the calendar. | 
|  | * @method after | 
|  | * @param {Date} date		The Date object to compare with the compare argument | 
|  | * @param {Date} compareTo	The Date object to use for the comparison | 
|  | * @return {Boolean} true if the date occurs after the compared date; false if not. | 
|  | */ | 
|  | after : function(date, compareTo) { | 
|  | var ms = compareTo.getTime(); | 
|  | if (date.getTime() > ms) { | 
|  | return true; | 
|  | } else { | 
|  | return false; | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Determines whether a given date is between two other dates on the calendar. | 
|  | * @method between | 
|  | * @param {Date} date		The date to check for | 
|  | * @param {Date} dateBegin	The start of the range | 
|  | * @param {Date} dateEnd		The end of the range | 
|  | * @return {Boolean} true if the date occurs between the compared dates; false if not. | 
|  | */ | 
|  | between : function(date, dateBegin, dateEnd) { | 
|  | if (this.after(date, dateBegin) && this.before(date, dateEnd)) { | 
|  | return true; | 
|  | } else { | 
|  | return false; | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Retrieves a JavaScript Date object representing January 1 of any given year. | 
|  | * @method getJan1 | 
|  | * @param {Number} calendarYear		The calendar year for which to retrieve January 1 | 
|  | * @return {Date}	January 1 of the calendar year specified. | 
|  | */ | 
|  | getJan1 : function(calendarYear) { | 
|  | return this.getDate(calendarYear,0,1); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Calculates the number of days the specified date is from January 1 of the specified calendar year. | 
|  | * Passing January 1 to this function would return an offset value of zero. | 
|  | * @method getDayOffset | 
|  | * @param {Date}	date	The JavaScript date for which to find the offset | 
|  | * @param {Number} calendarYear	The calendar year to use for determining the offset | 
|  | * @return {Number}	The number of days since January 1 of the given year | 
|  | */ | 
|  | getDayOffset : function(date, calendarYear) { | 
|  | var beginYear = this.getJan1(calendarYear); // Find the start of the year. This will be in week 1. | 
|  |  | 
|  | // Find the number of days the passed in date is away from the calendar year start | 
|  | var dayOffset = Math.ceil((date.getTime()-beginYear.getTime()) / this.ONE_DAY_MS); | 
|  | return dayOffset; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Calculates the week number for the given date. Can currently support standard | 
|  | * U.S. week numbers, based on Jan 1st defining the 1st week of the year, and | 
|  | * ISO8601 week numbers, based on Jan 4th defining the 1st week of the year. | 
|  | * | 
|  | * @method getWeekNumber | 
|  | * @param {Date}	date The JavaScript date for which to find the week number | 
|  | * @param {Number} firstDayOfWeek The index of the first day of the week (0 = Sun, 1 = Mon ... 6 = Sat). | 
|  | * Defaults to 0 | 
|  | * @param {Number} janDate The date in the first week of January which defines week one for the year | 
|  | * Defaults to the value of YAHOO.widget.DateMath.WEEK_ONE_JAN_DATE, which is 1 (Jan 1st). | 
|  | * For the U.S, this is normally Jan 1st. ISO8601 uses Jan 4th to define the first week of the year. | 
|  | * | 
|  | * @return {Number} The number of the week containing the given date. | 
|  | */ | 
|  | getWeekNumber : function(date, firstDayOfWeek, janDate) { | 
|  |  | 
|  | // Setup Defaults | 
|  | firstDayOfWeek = firstDayOfWeek || 0; | 
|  | janDate = janDate || this.WEEK_ONE_JAN_DATE; | 
|  |  | 
|  | var targetDate = this.clearTime(date), | 
|  | startOfWeek, | 
|  | endOfWeek; | 
|  |  | 
|  | if (targetDate.getDay() === firstDayOfWeek) { | 
|  | startOfWeek = targetDate; | 
|  | } else { | 
|  | startOfWeek = this.getFirstDayOfWeek(targetDate, firstDayOfWeek); | 
|  | } | 
|  |  | 
|  | var startYear = startOfWeek.getFullYear(), | 
|  | startTime = startOfWeek.getTime(); | 
|  |  | 
|  | // DST shouldn't be a problem here, math is quicker than setDate(); | 
|  | endOfWeek = new Date(startOfWeek.getTime() + 6*this.ONE_DAY_MS); | 
|  |  | 
|  | var weekNum; | 
|  | if (startYear !== endOfWeek.getFullYear() && endOfWeek.getDate() >= janDate) { | 
|  | // If years don't match, endOfWeek is in Jan. and if the | 
|  | // week has WEEK_ONE_JAN_DATE in it, it's week one by definition. | 
|  | weekNum = 1; | 
|  | } else { | 
|  | // Get the 1st day of the 1st week, and | 
|  | // find how many days away we are from it. | 
|  | var weekOne = this.clearTime(this.getDate(startYear, 0, janDate)), | 
|  | weekOneDayOne = this.getFirstDayOfWeek(weekOne, firstDayOfWeek); | 
|  |  | 
|  | // Round days to smoothen out 1 hr DST diff | 
|  | var daysDiff  = Math.round((targetDate.getTime() - weekOneDayOne.getTime())/this.ONE_DAY_MS); | 
|  |  | 
|  | // Calc. Full Weeks | 
|  | var rem = daysDiff % 7; | 
|  | var weeksDiff = (daysDiff - rem)/7; | 
|  | weekNum = weeksDiff + 1; | 
|  | } | 
|  | return weekNum; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Get the first day of the week, for the give date. | 
|  | * @param {Date} dt The date in the week for which the first day is required. | 
|  | * @param {Number} startOfWeek The index for the first day of the week, 0 = Sun, 1 = Mon ... 6 = Sat (defaults to 0) | 
|  | * @return {Date} The first day of the week | 
|  | */ | 
|  | getFirstDayOfWeek : function (dt, startOfWeek) { | 
|  | startOfWeek = startOfWeek || 0; | 
|  | var dayOfWeekIndex = dt.getDay(), | 
|  | dayOfWeek = (dayOfWeekIndex - startOfWeek + 7) % 7; | 
|  |  | 
|  | return this.subtract(dt, this.DAY, dayOfWeek); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Determines if a given week overlaps two different years. | 
|  | * @method isYearOverlapWeek | 
|  | * @param {Date}	weekBeginDate	The JavaScript Date representing the first day of the week. | 
|  | * @return {Boolean}	true if the date overlaps two different years. | 
|  | */ | 
|  | isYearOverlapWeek : function(weekBeginDate) { | 
|  | var overlaps = false; | 
|  | var nextWeek = this.add(weekBeginDate, this.DAY, 6); | 
|  | if (nextWeek.getFullYear() != weekBeginDate.getFullYear()) { | 
|  | overlaps = true; | 
|  | } | 
|  | return overlaps; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Determines if a given week overlaps two different months. | 
|  | * @method isMonthOverlapWeek | 
|  | * @param {Date}	weekBeginDate	The JavaScript Date representing the first day of the week. | 
|  | * @return {Boolean}	true if the date overlaps two different months. | 
|  | */ | 
|  | isMonthOverlapWeek : function(weekBeginDate) { | 
|  | var overlaps = false; | 
|  | var nextWeek = this.add(weekBeginDate, this.DAY, 6); | 
|  | if (nextWeek.getMonth() != weekBeginDate.getMonth()) { | 
|  | overlaps = true; | 
|  | } | 
|  | return overlaps; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Gets the first day of a month containing a given date. | 
|  | * @method findMonthStart | 
|  | * @param {Date}	date	The JavaScript Date used to calculate the month start | 
|  | * @return {Date}		The JavaScript Date representing the first day of the month | 
|  | */ | 
|  | findMonthStart : function(date) { | 
|  | var start = this.getDate(date.getFullYear(), date.getMonth(), 1); | 
|  | return start; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Gets the last day of a month containing a given date. | 
|  | * @method findMonthEnd | 
|  | * @param {Date}	date	The JavaScript Date used to calculate the month end | 
|  | * @return {Date}		The JavaScript Date representing the last day of the month | 
|  | */ | 
|  | findMonthEnd : function(date) { | 
|  | var start = this.findMonthStart(date); | 
|  | var nextMonth = this.add(start, this.MONTH, 1); | 
|  | var end = this.subtract(nextMonth, this.DAY, 1); | 
|  | return end; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Clears the time fields from a given date, effectively setting the time to 12 noon. | 
|  | * @method clearTime | 
|  | * @param {Date}	date	The JavaScript Date for which the time fields will be cleared | 
|  | * @return {Date}		The JavaScript Date cleared of all time fields | 
|  | */ | 
|  | clearTime : function(date) { | 
|  | date.setHours(12,0,0,0); | 
|  | return date; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Returns a new JavaScript Date object, representing the given year, month and date. Time fields (hr, min, sec, ms) on the new Date object | 
|  | * are set to 0. The method allows Date instances to be created with the a year less than 100. "new Date(year, month, date)" implementations | 
|  | * set the year to 19xx if a year (xx) which is less than 100 is provided. | 
|  | * <p> | 
|  | * <em>NOTE:</em>Validation on argument values is not performed. It is the caller's responsibility to ensure | 
|  | * arguments are valid as per the ECMAScript-262 Date object specification for the new Date(year, month[, date]) constructor. | 
|  | * </p> | 
|  | * @method getDate | 
|  | * @param {Number} y Year. | 
|  | * @param {Number} m Month index from 0 (Jan) to 11 (Dec). | 
|  | * @param {Number} d (optional) Date from 1 to 31. If not provided, defaults to 1. | 
|  | * @return {Date} The JavaScript date object with year, month, date set as provided. | 
|  | */ | 
|  | getDate : function(y, m, d) { | 
|  | var dt = null; | 
|  | if (YAHOO.lang.isUndefined(d)) { | 
|  | d = 1; | 
|  | } | 
|  | if (y >= 100) { | 
|  | dt = new Date(y, m, d); | 
|  | } else { | 
|  | dt = new Date(); | 
|  | dt.setFullYear(y); | 
|  | dt.setMonth(m); | 
|  | dt.setDate(d); | 
|  | dt.setHours(0,0,0,0); | 
|  | } | 
|  | return dt; | 
|  | } | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * The Calendar component is a UI control that enables users to choose one or more dates from a graphical calendar presented in a one-month or | 
|  | * multi-month interface. Calendars are generated entirely via script and can be navigated without any page refreshes. | 
|  | * @module    calendar | 
|  | * @title    Calendar | 
|  | * @namespace  YAHOO.widget | 
|  | * @requires  yahoo,dom,event | 
|  | */ | 
|  | (function(){ | 
|  |  | 
|  | var Dom = YAHOO.util.Dom, | 
|  | Event = YAHOO.util.Event, | 
|  | Lang = YAHOO.lang, | 
|  | DateMath = YAHOO.widget.DateMath; | 
|  |  | 
|  | /** | 
|  | * Calendar is the base class for the Calendar widget. In its most basic | 
|  | * implementation, it has the ability to render a calendar widget on the page | 
|  | * that can be manipulated to select a single date, move back and forth between | 
|  | * months and years. | 
|  | * <p>To construct the placeholder for the calendar widget, the code is as | 
|  | * follows: | 
|  | *	<xmp> | 
|  | *		<div id="calContainer"></div> | 
|  | *	</xmp> | 
|  | * </p> | 
|  | * <p> | 
|  | * <strong>NOTE: As of 2.4.0, the constructor's ID argument is optional.</strong> | 
|  | * The Calendar 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.Calendar("calContainer", configOptions); | 
|  | *	</xmp> | 
|  | * or: | 
|  | *   <xmp> | 
|  | *       var containerDiv = YAHOO.util.Dom.get("calContainer"); | 
|  | *		var c = new YAHOO.widget.Calendar(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 Calendar's ID will be set to "calContainer_t". | 
|  | * </p> | 
|  | * | 
|  | * @namespace YAHOO.widget | 
|  | * @class Calendar | 
|  | * @constructor | 
|  | * @param {String} id optional The id of the table element that will represent the Calendar 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 Calendar 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 Calendar. | 
|  | */ | 
|  | function Calendar(id, containerId, config) { | 
|  | this.init.apply(this, arguments); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * The path to be used for images loaded for the Calendar | 
|  | * @property YAHOO.widget.Calendar.IMG_ROOT | 
|  | * @static | 
|  | * @deprecated	You can now customize images by overriding the calclose, calnavleft and calnavright default CSS classes for the close icon, left arrow and right arrow respectively | 
|  | * @type String | 
|  | */ | 
|  | Calendar.IMG_ROOT = null; | 
|  |  | 
|  | /** | 
|  | * Type constant used for renderers to represent an individual date (M/D/Y) | 
|  | * @property YAHOO.widget.Calendar.DATE | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | Calendar.DATE = "D"; | 
|  |  | 
|  | /** | 
|  | * Type constant used for renderers to represent an individual date across any year (M/D) | 
|  | * @property YAHOO.widget.Calendar.MONTH_DAY | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | Calendar.MONTH_DAY = "MD"; | 
|  |  | 
|  | /** | 
|  | * Type constant used for renderers to represent a weekday | 
|  | * @property YAHOO.widget.Calendar.WEEKDAY | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | Calendar.WEEKDAY = "WD"; | 
|  |  | 
|  | /** | 
|  | * Type constant used for renderers to represent a range of individual dates (M/D/Y-M/D/Y) | 
|  | * @property YAHOO.widget.Calendar.RANGE | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | Calendar.RANGE = "R"; | 
|  |  | 
|  | /** | 
|  | * Type constant used for renderers to represent a month across any year | 
|  | * @property YAHOO.widget.Calendar.MONTH | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | Calendar.MONTH = "M"; | 
|  |  | 
|  | /** | 
|  | * Constant that represents the total number of date cells that are displayed in a given month | 
|  | * @property YAHOO.widget.Calendar.DISPLAY_DAYS | 
|  | * @static | 
|  | * @final | 
|  | * @type Number | 
|  | */ | 
|  | Calendar.DISPLAY_DAYS = 42; | 
|  |  | 
|  | /** | 
|  | * Constant used for halting the execution of the remainder of the render stack | 
|  | * @property YAHOO.widget.Calendar.STOP_RENDER | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | Calendar.STOP_RENDER = "S"; | 
|  |  | 
|  | /** | 
|  | * Constant used to represent short date field string formats (e.g. Tu or Feb) | 
|  | * @property YAHOO.widget.Calendar.SHORT | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | Calendar.SHORT = "short"; | 
|  |  | 
|  | /** | 
|  | * Constant used to represent long date field string formats (e.g. Monday or February) | 
|  | * @property YAHOO.widget.Calendar.LONG | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | Calendar.LONG = "long"; | 
|  |  | 
|  | /** | 
|  | * Constant used to represent medium date field string formats (e.g. Mon) | 
|  | * @property YAHOO.widget.Calendar.MEDIUM | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | Calendar.MEDIUM = "medium"; | 
|  |  | 
|  | /** | 
|  | * Constant used to represent single character date field string formats (e.g. M, T, W) | 
|  | * @property YAHOO.widget.Calendar.ONE_CHAR | 
|  | * @static | 
|  | * @final | 
|  | * @type String | 
|  | */ | 
|  | Calendar.ONE_CHAR = "1char"; | 
|  |  | 
|  | /** | 
|  | * The set of default Config property keys and values for the Calendar | 
|  | * @property YAHOO.widget.Calendar._DEFAULT_CONFIG | 
|  | * @final | 
|  | * @static | 
|  | * @private | 
|  | * @type Object | 
|  | */ | 
|  | Calendar._DEFAULT_CONFIG = { | 
|  | // Default values for pagedate and selected are not class level constants - they are set during instance creation | 
|  | PAGEDATE : {key:"pagedate", value:null}, | 
|  | SELECTED : {key:"selected", value:null}, | 
|  | TITLE : {key:"title", value:""}, | 
|  | CLOSE : {key:"close", value:false}, | 
|  | IFRAME : {key:"iframe", value:(YAHOO.env.ua.ie && YAHOO.env.ua.ie <= 6) ? true : false}, | 
|  | MINDATE : {key:"mindate", value:null}, | 
|  | MAXDATE : {key:"maxdate", value:null}, | 
|  | MULTI_SELECT : {key:"multi_select", value:false}, | 
|  | START_WEEKDAY : {key:"start_weekday", value:0}, | 
|  | SHOW_WEEKDAYS : {key:"show_weekdays", value:true}, | 
|  | SHOW_WEEK_HEADER : {key:"show_week_header", value:false}, | 
|  | SHOW_WEEK_FOOTER : {key:"show_week_footer", value:false}, | 
|  | HIDE_BLANK_WEEKS : {key:"hide_blank_weeks", value:false}, | 
|  | NAV_ARROW_LEFT: {key:"nav_arrow_left", value:null} , | 
|  | NAV_ARROW_RIGHT : {key:"nav_arrow_right", value:null} , | 
|  | MONTHS_SHORT : {key:"months_short", value:["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]}, | 
|  | MONTHS_LONG: {key:"months_long", value:["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]}, | 
|  | WEEKDAYS_1CHAR: {key:"weekdays_1char", value:["S", "M", "T", "W", "T", "F", "S"]}, | 
|  | WEEKDAYS_SHORT: {key:"weekdays_short", value:["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]}, | 
|  | WEEKDAYS_MEDIUM: {key:"weekdays_medium", value:["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]}, | 
|  | WEEKDAYS_LONG: {key:"weekdays_long", value:["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]}, | 
|  | LOCALE_MONTHS:{key:"locale_months", value:"long"}, | 
|  | LOCALE_WEEKDAYS:{key:"locale_weekdays", value:"short"}, | 
|  | DATE_DELIMITER:{key:"date_delimiter", value:","}, | 
|  | DATE_FIELD_DELIMITER:{key:"date_field_delimiter", value:"/"}, | 
|  | DATE_RANGE_DELIMITER:{key:"date_range_delimiter", value:"-"}, | 
|  | MY_MONTH_POSITION:{key:"my_month_position", value:1}, | 
|  | MY_YEAR_POSITION:{key:"my_year_position", value:2}, | 
|  | MD_MONTH_POSITION:{key:"md_month_position", value:1}, | 
|  | MD_DAY_POSITION:{key:"md_day_position", value:2}, | 
|  | MDY_MONTH_POSITION:{key:"mdy_month_position", value:1}, | 
|  | MDY_DAY_POSITION:{key:"mdy_day_position", value:2}, | 
|  | MDY_YEAR_POSITION:{key:"mdy_year_position", value:3}, | 
|  | MY_LABEL_MONTH_POSITION:{key:"my_label_month_position", value:1}, | 
|  | MY_LABEL_YEAR_POSITION:{key:"my_label_year_position", value:2}, | 
|  | MY_LABEL_MONTH_SUFFIX:{key:"my_label_month_suffix", value:" "}, | 
|  | MY_LABEL_YEAR_SUFFIX:{key:"my_label_year_suffix", value:""}, | 
|  | NAV: {key:"navigator", value: null}, | 
|  | STRINGS : { | 
|  | key:"strings", | 
|  | value: { | 
|  | previousMonth : "Previous Month", | 
|  | nextMonth : "Next Month", | 
|  | close: "Close" | 
|  | }, | 
|  | supercedes : ["close", "title"] | 
|  | } | 
|  | }; | 
|  |  | 
|  | var DEF_CFG = Calendar._DEFAULT_CONFIG; | 
|  |  | 
|  | /** | 
|  | * The set of Custom Event types supported by the Calendar | 
|  | * @property YAHOO.widget.Calendar._EVENT_TYPES | 
|  | * @final | 
|  | * @static | 
|  | * @private | 
|  | * @type Object | 
|  | */ | 
|  | Calendar._EVENT_TYPES = { | 
|  | BEFORE_SELECT : "beforeSelect", | 
|  | SELECT : "select", | 
|  | BEFORE_DESELECT : "beforeDeselect", | 
|  | DESELECT : "deselect", | 
|  | CHANGE_PAGE : "changePage", | 
|  | BEFORE_RENDER : "beforeRender", | 
|  | RENDER : "render", | 
|  | BEFORE_DESTROY : "beforeDestroy", | 
|  | DESTROY : "destroy", | 
|  | RESET : "reset", | 
|  | CLEAR : "clear", | 
|  | BEFORE_HIDE : "beforeHide", | 
|  | HIDE : "hide", | 
|  | BEFORE_SHOW : "beforeShow", | 
|  | SHOW : "show", | 
|  | BEFORE_HIDE_NAV : "beforeHideNav", | 
|  | HIDE_NAV : "hideNav", | 
|  | BEFORE_SHOW_NAV : "beforeShowNav", | 
|  | SHOW_NAV : "showNav", | 
|  | BEFORE_RENDER_NAV : "beforeRenderNav", | 
|  | RENDER_NAV : "renderNav" | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * The set of default style constants for the Calendar | 
|  | * @property YAHOO.widget.Calendar._STYLES | 
|  | * @final | 
|  | * @static | 
|  | * @private | 
|  | * @type Object | 
|  | */ | 
|  | Calendar._STYLES = { | 
|  | CSS_ROW_HEADER: "calrowhead", | 
|  | CSS_ROW_FOOTER: "calrowfoot", | 
|  | CSS_CELL : "calcell", | 
|  | CSS_CELL_SELECTOR : "selector", | 
|  | CSS_CELL_SELECTED : "selected", | 
|  | CSS_CELL_SELECTABLE : "selectable", | 
|  | CSS_CELL_RESTRICTED : "restricted", | 
|  | CSS_CELL_TODAY : "today", | 
|  | CSS_CELL_OOM : "oom", | 
|  | CSS_CELL_OOB : "previous", | 
|  | CSS_HEADER : "calheader", | 
|  | CSS_HEADER_TEXT : "calhead", | 
|  | CSS_BODY : "calbody", | 
|  | CSS_WEEKDAY_CELL : "calweekdaycell", | 
|  | CSS_WEEKDAY_ROW : "calweekdayrow", | 
|  | CSS_FOOTER : "calfoot", | 
|  | CSS_CALENDAR : "yui-calendar", | 
|  | CSS_SINGLE : "single", | 
|  | CSS_CONTAINER : "yui-calcontainer", | 
|  | CSS_NAV_LEFT : "calnavleft", | 
|  | CSS_NAV_RIGHT : "calnavright", | 
|  | CSS_NAV : "calnav", | 
|  | CSS_CLOSE : "calclose", | 
|  | CSS_CELL_TOP : "calcelltop", | 
|  | CSS_CELL_LEFT : "calcellleft", | 
|  | CSS_CELL_RIGHT : "calcellright", | 
|  | CSS_CELL_BOTTOM : "calcellbottom", | 
|  | CSS_CELL_HOVER : "calcellhover", | 
|  | CSS_CELL_HIGHLIGHT1 : "highlight1", | 
|  | CSS_CELL_HIGHLIGHT2 : "highlight2", | 
|  | CSS_CELL_HIGHLIGHT3 : "highlight3", | 
|  | CSS_CELL_HIGHLIGHT4 : "highlight4" | 
|  | }; | 
|  |  | 
|  | Calendar.prototype = { | 
|  |  | 
|  | /** | 
|  | * The configuration object used to set up the calendars various locale and style options. | 
|  | * @property Config | 
|  | * @private | 
|  | * @deprecated Configuration properties should be set by calling Calendar.cfg.setProperty. | 
|  | * @type Object | 
|  | */ | 
|  | Config : null, | 
|  |  | 
|  | /** | 
|  | * The parent CalendarGroup, only to be set explicitly by the parent group | 
|  | * @property parent | 
|  | * @type CalendarGroup | 
|  | */ | 
|  | parent : null, | 
|  |  | 
|  | /** | 
|  | * The index of this item in the parent group | 
|  | * @property index | 
|  | * @type Number | 
|  | */ | 
|  | index : -1, | 
|  |  | 
|  | /** | 
|  | * The collection of calendar table cells | 
|  | * @property cells | 
|  | * @type HTMLTableCellElement[] | 
|  | */ | 
|  | cells : null, | 
|  |  | 
|  | /** | 
|  | * The collection of calendar cell dates that is parallel to the cells collection. The array contains dates field arrays in the format of [YYYY, M, D]. | 
|  | * @property cellDates | 
|  | * @type Array[](Number[]) | 
|  | */ | 
|  | cellDates : null, | 
|  |  | 
|  | /** | 
|  | * The id that uniquely identifies this Calendar. | 
|  | * @property id | 
|  | * @type String | 
|  | */ | 
|  | id : null, | 
|  |  | 
|  | /** | 
|  | * The unique id associated with the Calendar's container | 
|  | * @property containerId | 
|  | * @type String | 
|  | */ | 
|  | containerId: null, | 
|  |  | 
|  | /** | 
|  | * The DOM element reference that points to this calendar's container element. The calendar will be inserted into this element when the shell is rendered. | 
|  | * @property oDomContainer | 
|  | * @type HTMLElement | 
|  | */ | 
|  | oDomContainer : null, | 
|  |  | 
|  | /** | 
|  | * A Date object representing today's date. | 
|  | * @property today | 
|  | * @type Date | 
|  | */ | 
|  | today : null, | 
|  |  | 
|  | /** | 
|  | * The list of render functions, along with required parameters, used to render cells. | 
|  | * @property renderStack | 
|  | * @type Array[] | 
|  | */ | 
|  | renderStack : null, | 
|  |  | 
|  | /** | 
|  | * A copy of the initial render functions created before rendering. | 
|  | * @property _renderStack | 
|  | * @private | 
|  | * @type Array | 
|  | */ | 
|  | _renderStack : null, | 
|  |  | 
|  | /** | 
|  | * A reference to the CalendarNavigator instance created for this Calendar. | 
|  | * Will be null if the "navigator" configuration property has not been set | 
|  | * @property oNavigator | 
|  | * @type CalendarNavigator | 
|  | */ | 
|  | oNavigator : null, | 
|  |  | 
|  | /** | 
|  | * The private list of initially selected dates. | 
|  | * @property _selectedDates | 
|  | * @private | 
|  | * @type Array | 
|  | */ | 
|  | _selectedDates : null, | 
|  |  | 
|  | /** | 
|  | * A map of DOM event handlers to attach to cells associated with specific CSS class names | 
|  | * @property domEventMap | 
|  | * @type Object | 
|  | */ | 
|  | domEventMap : null, | 
|  |  | 
|  | /** | 
|  | * Protected helper used to parse Calendar constructor/init arguments. | 
|  | * | 
|  | * As of 2.4.0, Calendar supports a simpler constructor | 
|  | * signature. This method reconciles arguments | 
|  | * received in the pre 2.4.0 and 2.4.0 formats. | 
|  | * | 
|  | * @protected | 
|  | * @method _parseArgs | 
|  | * @param {Array} Function "arguments" array | 
|  | * @return {Object} Object with id, container, config properties containing | 
|  | * the reconciled argument values. | 
|  | **/ | 
|  | _parseArgs : function(args) { | 
|  | /* | 
|  | 2.4.0 Constructors signatures | 
|  |  | 
|  | new Calendar(String) | 
|  | new Calendar(HTMLElement) | 
|  | new Calendar(String, ConfigObject) | 
|  | new Calendar(HTMLElement, ConfigObject) | 
|  |  | 
|  | Pre 2.4.0 Constructor signatures | 
|  |  | 
|  | new Calendar(String, String) | 
|  | new Calendar(String, HTMLElement) | 
|  | new Calendar(String, String, ConfigObject) | 
|  | new Calendar(String, HTMLElement, ConfigObject) | 
|  | */ | 
|  | var nArgs = {id:null, container:null, config:null}; | 
|  |  | 
|  | if (args && args.length && args.length > 0) { | 
|  | switch (args.length) { | 
|  | case 1: | 
|  | nArgs.id = null; | 
|  | nArgs.container = args[0]; | 
|  | nArgs.config = null; | 
|  | break; | 
|  | case 2: | 
|  | if (Lang.isObject(args[1]) && !args[1].tagName && !(args[1] instanceof String)) { | 
|  | nArgs.id = null; | 
|  | nArgs.container = args[0]; | 
|  | nArgs.config = args[1]; | 
|  | } else { | 
|  | nArgs.id = args[0]; | 
|  | nArgs.container = args[1]; | 
|  | nArgs.config = null; | 
|  | } | 
|  | break; | 
|  | default: // 3+ | 
|  | nArgs.id = args[0]; | 
|  | nArgs.container = args[1]; | 
|  | nArgs.config = args[2]; | 
|  | break; | 
|  | } | 
|  | } else { | 
|  | } | 
|  | return nArgs; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Initializes the Calendar widget. | 
|  | * @method init | 
|  | * | 
|  | * @param {String} id optional The id of the table element that will represent the Calendar 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 Calendar 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 Calendar. | 
|  | */ | 
|  | 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.id) { | 
|  | this.oDomContainer.id = Dom.generateId(); | 
|  | } | 
|  | if (!id) { | 
|  | id = this.oDomContainer.id + "_t"; | 
|  | } | 
|  |  | 
|  | this.id = id; | 
|  | this.containerId = this.oDomContainer.id; | 
|  |  | 
|  | this.initEvents(); | 
|  |  | 
|  | this.today = new Date(); | 
|  | DateMath.clearTime(this.today); | 
|  |  | 
|  | /** | 
|  | * The Config object used to hold the configuration variables for the Calendar | 
|  | * @property cfg | 
|  | * @type YAHOO.util.Config | 
|  | */ | 
|  | this.cfg = new YAHOO.util.Config(this); | 
|  |  | 
|  | /** | 
|  | * The local object which contains the Calendar's options | 
|  | * @property Options | 
|  | * @type Object | 
|  | */ | 
|  | this.Options = {}; | 
|  |  | 
|  | /** | 
|  | * The local object which contains the Calendar's locale settings | 
|  | * @property Locale | 
|  | * @type Object | 
|  | */ | 
|  | this.Locale = {}; | 
|  |  | 
|  | this.initStyles(); | 
|  |  | 
|  | Dom.addClass(this.oDomContainer, this.Style.CSS_CONTAINER); | 
|  | Dom.addClass(this.oDomContainer, this.Style.CSS_SINGLE); | 
|  |  | 
|  | this.cellDates = []; | 
|  | this.cells = []; | 
|  | this.renderStack = []; | 
|  | this._renderStack = []; | 
|  |  | 
|  | this.setupConfig(); | 
|  |  | 
|  | if (config) { | 
|  | this.cfg.applyConfig(config, true); | 
|  | } | 
|  |  | 
|  | this.cfg.fireQueue(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Default Config listener for the iframe property. If the iframe config property is set to true, | 
|  | * renders the built-in IFRAME shim if the container is relatively or absolutely positioned. | 
|  | * | 
|  | * @method configIframe | 
|  | */ | 
|  | configIframe : function(type, args, obj) { | 
|  | var useIframe = args[0]; | 
|  |  | 
|  | if (!this.parent) { | 
|  | if (Dom.inDocument(this.oDomContainer)) { | 
|  | if (useIframe) { | 
|  | var pos = Dom.getStyle(this.oDomContainer, "position"); | 
|  |  | 
|  | if (pos == "absolute" || pos == "relative") { | 
|  |  | 
|  | if (!Dom.inDocument(this.iframe)) { | 
|  | this.iframe = document.createElement("iframe"); | 
|  | this.iframe.src = "javascript:false;"; | 
|  |  | 
|  | Dom.setStyle(this.iframe, "opacity", "0"); | 
|  |  | 
|  | if (YAHOO.env.ua.ie && YAHOO.env.ua.ie <= 6) { | 
|  | Dom.addClass(this.iframe, "fixedsize"); | 
|  | } | 
|  |  | 
|  | this.oDomContainer.insertBefore(this.iframe, this.oDomContainer.firstChild); | 
|  | } | 
|  | } | 
|  | } else { | 
|  | if (this.iframe) { | 
|  | if (this.iframe.parentNode) { | 
|  | this.iframe.parentNode.removeChild(this.iframe); | 
|  | } | 
|  | this.iframe = null; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Default handler for the "title" property | 
|  | * @method configTitle | 
|  | */ | 
|  | configTitle : function(type, args, obj) { | 
|  | var title = args[0]; | 
|  |  | 
|  | // "" disables title bar | 
|  | if (title) { | 
|  | this.createTitleBar(title); | 
|  | } else { | 
|  | var close = this.cfg.getProperty(DEF_CFG.CLOSE.key); | 
|  | if (!close) { | 
|  | this.removeTitleBar(); | 
|  | } else { | 
|  | this.createTitleBar(" "); | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Default handler for the "close" property | 
|  | * @method configClose | 
|  | */ | 
|  | configClose : function(type, args, obj) { | 
|  | var close = args[0], | 
|  | title = this.cfg.getProperty(DEF_CFG.TITLE.key); | 
|  |  | 
|  | if (close) { | 
|  | if (!title) { | 
|  | this.createTitleBar(" "); | 
|  | } | 
|  | this.createCloseButton(); | 
|  | } else { | 
|  | this.removeCloseButton(); | 
|  | if (!title) { | 
|  | this.removeTitleBar(); | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Initializes Calendar's built-in CustomEvents | 
|  | * @method initEvents | 
|  | */ | 
|  | initEvents : function() { | 
|  |  | 
|  | var defEvents = Calendar._EVENT_TYPES, | 
|  | CE = YAHOO.util.CustomEvent, | 
|  | cal = this; // To help with minification | 
|  |  | 
|  | /** | 
|  | * Fired before a selection is made | 
|  | * @event beforeSelectEvent | 
|  | */ | 
|  | cal.beforeSelectEvent = new CE(defEvents.BEFORE_SELECT); | 
|  |  | 
|  | /** | 
|  | * Fired when a selection is made | 
|  | * @event selectEvent | 
|  | * @param {Array}	Array of Date field arrays in the format [YYYY, MM, DD]. | 
|  | */ | 
|  | cal.selectEvent = new CE(defEvents.SELECT); | 
|  |  | 
|  | /** | 
|  | * Fired before a selection is made | 
|  | * @event beforeDeselectEvent | 
|  | */ | 
|  | cal.beforeDeselectEvent = new CE(defEvents.BEFORE_DESELECT); | 
|  |  | 
|  | /** | 
|  | * Fired when a selection is made | 
|  | * @event deselectEvent | 
|  | * @param {Array}	Array of Date field arrays in the format [YYYY, MM, DD]. | 
|  | */ | 
|  | cal.deselectEvent = new CE(defEvents.DESELECT); | 
|  |  | 
|  | /** | 
|  | * Fired when the Calendar page is changed | 
|  | * @event changePageEvent | 
|  | */ | 
|  | cal.changePageEvent = new CE(defEvents.CHANGE_PAGE); | 
|  |  | 
|  | /** | 
|  | * Fired before the Calendar is rendered | 
|  | * @event beforeRenderEvent | 
|  | */ | 
|  | cal.beforeRenderEvent = new CE(defEvents.BEFORE_RENDER); | 
|  |  | 
|  | /** | 
|  | * Fired when the Calendar is rendered | 
|  | * @event renderEvent | 
|  | */ | 
|  | cal.renderEvent = new CE(defEvents.RENDER); | 
|  |  | 
|  | /** | 
|  | * Fired just before the Calendar is to be destroyed | 
|  | * @event beforeDestroyEvent | 
|  | */ | 
|  | cal.beforeDestroyEvent = new CE(defEvents.BEFORE_DESTROY); | 
|  |  | 
|  | /** | 
|  | * Fired after the Calendar is destroyed. This event should be used | 
|  | * for notification only. When this event is fired, important Calendar instance | 
|  | * properties, dom references and event listeners have already been | 
|  | * removed/dereferenced, and hence the Calendar instance is not in a usable | 
|  | * state. | 
|  | * | 
|  | * @event destroyEvent | 
|  | */ | 
|  | cal.destroyEvent = new CE(defEvents.DESTROY); | 
|  |  | 
|  | /** | 
|  | * Fired when the Calendar is reset | 
|  | * @event resetEvent | 
|  | */ | 
|  | cal.resetEvent = new CE(defEvents.RESET); | 
|  |  | 
|  | /** | 
|  | * Fired when the Calendar is cleared | 
|  | * @event clearEvent | 
|  | */ | 
|  | cal.clearEvent = new CE(defEvents.CLEAR); | 
|  |  | 
|  | /** | 
|  | * Fired just before the Calendar is to be shown | 
|  | * @event beforeShowEvent | 
|  | */ | 
|  | cal.beforeShowEvent = new CE(defEvents.BEFORE_SHOW); | 
|  |  | 
|  | /** | 
|  | * Fired after the Calendar is shown | 
|  | * @event showEvent | 
|  | */ | 
|  | cal.showEvent = new CE(defEvents.SHOW); | 
|  |  | 
|  | /** | 
|  | * Fired just before the Calendar is to be hidden | 
|  | * @event beforeHideEvent | 
|  | */ | 
|  | cal.beforeHideEvent = new CE(defEvents.BEFORE_HIDE); | 
|  |  | 
|  | /** | 
|  | * Fired after the Calendar is hidden | 
|  | * @event hideEvent | 
|  | */ | 
|  | cal.hideEvent = new CE(defEvents.HIDE); | 
|  |  | 
|  | /** | 
|  | * Fired just before the CalendarNavigator is to be shown | 
|  | * @event beforeShowNavEvent | 
|  | */ | 
|  | cal.beforeShowNavEvent = new CE(defEvents.BEFORE_SHOW_NAV); | 
|  |  | 
|  | /** | 
|  | * Fired after the CalendarNavigator is shown | 
|  | * @event showNavEvent | 
|  | */ | 
|  | cal.showNavEvent = new CE(defEvents.SHOW_NAV); | 
|  |  | 
|  | /** | 
|  | * Fired just before the CalendarNavigator is to be hidden | 
|  | * @event beforeHideNavEvent | 
|  | */ | 
|  | cal.beforeHideNavEvent = new CE(defEvents.BEFORE_HIDE_NAV); | 
|  |  | 
|  | /** | 
|  | * Fired after the CalendarNavigator is hidden | 
|  | * @event hideNavEvent | 
|  | */ | 
|  | cal.hideNavEvent = new CE(defEvents.HIDE_NAV); | 
|  |  | 
|  | /** | 
|  | * Fired just before the CalendarNavigator is to be rendered | 
|  | * @event beforeRenderNavEvent | 
|  | */ | 
|  | cal.beforeRenderNavEvent = new CE(defEvents.BEFORE_RENDER_NAV); | 
|  |  | 
|  | /** | 
|  | * Fired after the CalendarNavigator is rendered | 
|  | * @event renderNavEvent | 
|  | */ | 
|  | cal.renderNavEvent = new CE(defEvents.RENDER_NAV); | 
|  |  | 
|  | cal.beforeSelectEvent.subscribe(cal.onBeforeSelect, this, true); | 
|  | cal.selectEvent.subscribe(cal.onSelect, this, true); | 
|  | cal.beforeDeselectEvent.subscribe(cal.onBeforeDeselect, this, true); | 
|  | cal.deselectEvent.subscribe(cal.onDeselect, this, true); | 
|  | cal.changePageEvent.subscribe(cal.onChangePage, this, true); | 
|  | cal.renderEvent.subscribe(cal.onRender, this, true); | 
|  | cal.resetEvent.subscribe(cal.onReset, this, true); | 
|  | cal.clearEvent.subscribe(cal.onClear, this, true); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The default event handler for clicks on the "Previous Month" navigation UI | 
|  | * | 
|  | * @method doPreviousMonthNav | 
|  | * @param {DOMEvent} e	The DOM event | 
|  | * @param {Calendar} cal	A reference to the calendar | 
|  | */ | 
|  | doPreviousMonthNav : function(e, cal) { | 
|  | Event.preventDefault(e); | 
|  | // previousMonth invoked in a timeout, to allow | 
|  | // event to bubble up, with correct target. Calling | 
|  | // previousMonth, will call render which will remove | 
|  | // HTML which generated the event, resulting in an | 
|  | // invalid event target in certain browsers. | 
|  | setTimeout(function() { | 
|  | cal.previousMonth(); | 
|  | var navs = Dom.getElementsByClassName(cal.Style.CSS_NAV_LEFT, "a", cal.oDomContainer); | 
|  | if (navs && navs[0]) { | 
|  | try { | 
|  | navs[0].focus(); | 
|  | } catch (e) { | 
|  | // ignore | 
|  | } | 
|  | } | 
|  | }, 0); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The default event handler for clicks on the "Next Month" navigation UI | 
|  | * | 
|  | * @method doNextMonthNav | 
|  | * @param {DOMEvent} e	The DOM event | 
|  | * @param {Calendar} cal	A reference to the calendar | 
|  | */ | 
|  | doNextMonthNav : function(e, cal) { | 
|  | Event.preventDefault(e); | 
|  | setTimeout(function() { | 
|  | cal.nextMonth(); | 
|  | var navs = Dom.getElementsByClassName(cal.Style.CSS_NAV_RIGHT, "a", cal.oDomContainer); | 
|  | if (navs && navs[0]) { | 
|  | try { | 
|  | navs[0].focus(); | 
|  | } catch (e) { | 
|  | // ignore | 
|  | } | 
|  | } | 
|  | }, 0); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The default event handler for date cell selection. Currently attached to | 
|  | * the Calendar's bounding box, referenced by it's <a href="#property_oDomContainer">oDomContainer</a> property. | 
|  | * | 
|  | * @method doSelectCell | 
|  | * @param {DOMEvent} e	The DOM event | 
|  | * @param {Calendar} cal	A reference to the calendar | 
|  | */ | 
|  | doSelectCell : function(e, cal) { | 
|  | var cell, d, date, index; | 
|  |  | 
|  | var target = Event.getTarget(e), | 
|  | tagName = target.tagName.toLowerCase(), | 
|  | defSelector = false; | 
|  |  | 
|  | while (tagName != "td" && !Dom.hasClass(target, cal.Style.CSS_CELL_SELECTABLE)) { | 
|  |  | 
|  | if (!defSelector && tagName == "a" && Dom.hasClass(target, cal.Style.CSS_CELL_SELECTOR)) { | 
|  | defSelector = true; | 
|  | } | 
|  |  | 
|  | target = target.parentNode; | 
|  | tagName = target.tagName.toLowerCase(); | 
|  |  | 
|  | if (target == this.oDomContainer || tagName == "html") { | 
|  | return; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (defSelector) { | 
|  | // Stop link href navigation for default renderer | 
|  | Event.preventDefault(e); | 
|  | } | 
|  |  | 
|  | cell = target; | 
|  |  | 
|  | if (Dom.hasClass(cell, cal.Style.CSS_CELL_SELECTABLE)) { | 
|  | index = cal.getIndexFromId(cell.id); | 
|  | if (index > -1) { | 
|  | d = cal.cellDates[index]; | 
|  | if (d) { | 
|  | date = DateMath.getDate(d[0],d[1]-1,d[2]); | 
|  |  | 
|  | var link; | 
|  |  | 
|  | if (cal.Options.MULTI_SELECT) { | 
|  | link = cell.getElementsByTagName("a")[0]; | 
|  | if (link) { | 
|  | link.blur(); | 
|  | } | 
|  |  | 
|  | var cellDate = cal.cellDates[index]; | 
|  | var cellDateIndex = cal._indexOfSelectedFieldArray(cellDate); | 
|  |  | 
|  | if (cellDateIndex > -1) { | 
|  | cal.deselectCell(index); | 
|  | } else { | 
|  | cal.selectCell(index); | 
|  | } | 
|  |  | 
|  | } else { | 
|  | link = cell.getElementsByTagName("a")[0]; | 
|  | if (link) { | 
|  | link.blur(); | 
|  | } | 
|  | cal.selectCell(index); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The event that is executed when the user hovers over a cell | 
|  | * @method doCellMouseOver | 
|  | * @param {DOMEvent} e	The event | 
|  | * @param {Calendar} cal	A reference to the calendar passed by the Event utility | 
|  | */ | 
|  | doCellMouseOver : function(e, cal) { | 
|  | var target; | 
|  | if (e) { | 
|  | target = Event.getTarget(e); | 
|  | } else { | 
|  | target = this; | 
|  | } | 
|  |  | 
|  | while (target.tagName && target.tagName.toLowerCase() != "td") { | 
|  | target = target.parentNode; | 
|  | if (!target.tagName || target.tagName.toLowerCase() == "html") { | 
|  | return; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (Dom.hasClass(target, cal.Style.CSS_CELL_SELECTABLE)) { | 
|  | Dom.addClass(target, cal.Style.CSS_CELL_HOVER); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The event that is executed when the user moves the mouse out of a cell | 
|  | * @method doCellMouseOut | 
|  | * @param {DOMEvent} e	The event | 
|  | * @param {Calendar} cal	A reference to the calendar passed by the Event utility | 
|  | */ | 
|  | doCellMouseOut : function(e, cal) { | 
|  | var target; | 
|  | if (e) { | 
|  | target = Event.getTarget(e); | 
|  | } else { | 
|  | target = this; | 
|  | } | 
|  |  | 
|  | while (target.tagName && target.tagName.toLowerCase() != "td") { | 
|  | target = target.parentNode; | 
|  | if (!target.tagName || target.tagName.toLowerCase() == "html") { | 
|  | return; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (Dom.hasClass(target, cal.Style.CSS_CELL_SELECTABLE)) { | 
|  | Dom.removeClass(target, cal.Style.CSS_CELL_HOVER); | 
|  | } | 
|  | }, | 
|  |  | 
|  | setupConfig : function() { | 
|  | var cfg = this.cfg; | 
|  |  | 
|  | /** | 
|  | * 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 Calendar'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 Calendar | 
|  | * @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.configMinDate } ); | 
|  |  | 
|  | /** | 
|  | * 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.configMaxDate } ); | 
|  |  | 
|  |  | 
|  | // 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.configOptions, validator:cfg.checkBoolean } ); | 
|  |  | 
|  | /** | 
|  | * The weekday the week begins on. Default is 0 (Sunday = 0, Monday = 1 ... Saturday = 6). | 
|  | * @config START_WEEKDAY | 
|  | * @type number | 
|  | * @default 0 | 
|  | */ | 
|  | cfg.addProperty(DEF_CFG.START_WEEKDAY.key,	{ value:DEF_CFG.START_WEEKDAY.value, handler:this.configOptions, 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.configOptions, 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.configOptions, 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.configOptions, 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.configOptions, 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.configOptions } ); | 
|  |  | 
|  | /** | 
|  | * 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.configOptions } ); | 
|  |  | 
|  | // 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.configLocale } ); | 
|  |  | 
|  | /** | 
|  | * 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.configLocale } ); | 
|  |  | 
|  | /** | 
|  | * 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.configLocale } ); | 
|  |  | 
|  | /** | 
|  | * 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.configLocale } ); | 
|  |  | 
|  | /** | 
|  | * 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.configLocale } ); | 
|  |  | 
|  | /** | 
|  | * 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.configLocale } ); | 
|  |  | 
|  | /** | 
|  | * Refreshes the locale values used to build the Calendar. | 
|  | * @method refreshLocale | 
|  | * @private | 
|  | */ | 
|  | var refreshLocale = function() { | 
|  | cfg.refireEvent(DEF_CFG.LOCALE_MONTHS.key); | 
|  | cfg.refireEvent(DEF_CFG.LOCALE_WEEKDAYS.key); | 
|  | }; | 
|  |  | 
|  | cfg.subscribeToConfigEvent(DEF_CFG.START_WEEKDAY.key, refreshLocale, this, true); | 
|  | cfg.subscribeToConfigEvent(DEF_CFG.MONTHS_SHORT.key, refreshLocale, this, true); | 
|  | cfg.subscribeToConfigEvent(DEF_CFG.MONTHS_LONG.key, refreshLocale, this, true); | 
|  | cfg.subscribeToConfigEvent(DEF_CFG.WEEKDAYS_1CHAR.key, refreshLocale, this, true); | 
|  | cfg.subscribeToConfigEvent(DEF_CFG.WEEKDAYS_SHORT.key, refreshLocale, this, true); | 
|  | cfg.subscribeToConfigEvent(DEF_CFG.WEEKDAYS_MEDIUM.key, refreshLocale, this, true); | 
|  | cfg.subscribeToConfigEvent(DEF_CFG.WEEKDAYS_LONG.key, refreshLocale, this, true); | 
|  |  | 
|  | /** | 
|  | * 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.configLocaleValues } ); | 
|  |  | 
|  | /** | 
|  | * 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.configLocaleValues } ); | 
|  |  | 
|  | /** | 
|  | * 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.configLocale } ); | 
|  |  | 
|  | /** | 
|  | * 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.configLocale } ); | 
|  |  | 
|  | /** | 
|  | * 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.configLocale } ); | 
|  |  | 
|  | /** | 
|  | * 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.configLocale, 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.configLocale, 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.configLocale, 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.configLocale, 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.configLocale, 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.configLocale, 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.configLocale, 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.configLocale, 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.configLocale, 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.configLocale } ); | 
|  |  | 
|  | /** | 
|  | * 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.configLocale } ); | 
|  |  | 
|  | /** | 
|  | * Configuration for the Month/Year CalendarNavigator UI which allows the user to jump directly to a | 
|  | * specific Month/Year without having to scroll sequentially through months. | 
|  | * <p> | 
|  | * Setting this property to null (default value) or false, will disable the CalendarNavigator UI. | 
|  | * </p> | 
|  | * <p> | 
|  | * Setting this property to true will enable the CalendarNavigatior UI with the default CalendarNavigator configuration values. | 
|  | * </p> | 
|  | * <p> | 
|  | * This property can also be set to an object literal containing configuration properties for the CalendarNavigator UI. | 
|  | * The configuration object expects the the following case-sensitive properties, with the "strings" property being a nested object. | 
|  | * Any properties which are not provided will use the default values (defined in the CalendarNavigator class). | 
|  | * </p> | 
|  | * <dl> | 
|  | * <dt>strings</dt> | 
|  | * <dd><em>Object</em> :  An object with the properties shown below, defining the string labels to use in the Navigator's UI | 
|  | *     <dl> | 
|  | *         <dt>month</dt><dd><em>String</em> : The string to use for the month label. Defaults to "Month".</dd> | 
|  | *         <dt>year</dt><dd><em>String</em> : The string to use for the year label. Defaults to "Year".</dd> | 
|  | *         <dt>submit</dt><dd><em>String</em> : The string to use for the submit button label. Defaults to "Okay".</dd> | 
|  | *         <dt>cancel</dt><dd><em>String</em> : The string to use for the cancel button label. Defaults to "Cancel".</dd> | 
|  | *         <dt>invalidYear</dt><dd><em>String</em> : The string to use for invalid year values. Defaults to "Year needs to be a number".</dd> | 
|  | *     </dl> | 
|  | * </dd> | 
|  | * <dt>monthFormat</dt><dd><em>String</em> : The month format to use. Either YAHOO.widget.Calendar.LONG, or YAHOO.widget.Calendar.SHORT. Defaults to YAHOO.widget.Calendar.LONG</dd> | 
|  | * <dt>initialFocus</dt><dd><em>String</em> : Either "year" or "month" specifying which input control should get initial focus. Defaults to "year"</dd> | 
|  | * </dl> | 
|  | * <p>E.g.</p> | 
|  | * <pre> | 
|  | * var navConfig = { | 
|  | *	  strings: { | 
|  | *		  month:"Calendar Month", | 
|  | *		  year:"Calendar Year", | 
|  | *		  submit: "Submit", | 
|  | *		  cancel: "Cancel", | 
|  | *		  invalidYear: "Please enter a valid year" | 
|  | *	  }, | 
|  | *	  monthFormat: YAHOO.widget.Calendar.SHORT, | 
|  | *	  initialFocus: "month" | 
|  | * } | 
|  | * </pre> | 
|  | * @config navigator | 
|  | * @type {Object|Boolean} | 
|  | * @default null | 
|  | */ | 
|  | cfg.addProperty(DEF_CFG.NAV.key, { value:DEF_CFG.NAV.value, handler:this.configNavigator } ); | 
|  |  | 
|  | /** | 
|  | * The map of UI strings which the Calendar 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 | 
|  | }); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The default handler for the "strings" property | 
|  | * @method configStrings | 
|  | */ | 
|  | configStrings : function(type, args, obj) { | 
|  | var val = Lang.merge(DEF_CFG.STRINGS.value, args[0]); | 
|  | this.cfg.setProperty(DEF_CFG.STRINGS.key, val, true); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The default handler for the "pagedate" property | 
|  | * @method configPageDate | 
|  | */ | 
|  | configPageDate : function(type, args, obj) { | 
|  | this.cfg.setProperty(DEF_CFG.PAGEDATE.key, this._parsePageDate(args[0]), true); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The default handler for the "mindate" property | 
|  | * @method configMinDate | 
|  | */ | 
|  | configMinDate : function(type, args, obj) { | 
|  | var val = args[0]; | 
|  | if (Lang.isString(val)) { | 
|  | val = this._parseDate(val); | 
|  | this.cfg.setProperty(DEF_CFG.MINDATE.key, DateMath.getDate(val[0],(val[1]-1),val[2])); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The default handler for the "maxdate" property | 
|  | * @method configMaxDate | 
|  | */ | 
|  | configMaxDate : function(type, args, obj) { | 
|  | var val = args[0]; | 
|  | if (Lang.isString(val)) { | 
|  | val = this._parseDate(val); | 
|  | this.cfg.setProperty(DEF_CFG.MAXDATE.key, DateMath.getDate(val[0],(val[1]-1),val[2])); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The default handler for the "selected" property | 
|  | * @method configSelected | 
|  | */ | 
|  | configSelected : function(type, args, obj) { | 
|  | var selected = args[0], | 
|  | cfgSelected = DEF_CFG.SELECTED.key; | 
|  |  | 
|  | if (selected) { | 
|  | if (Lang.isString(selected)) { | 
|  | this.cfg.setProperty(cfgSelected, this._parseDates(selected), true); | 
|  | } | 
|  | } | 
|  | if (! this._selectedDates) { | 
|  | this._selectedDates = this.cfg.getProperty(cfgSelected); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The default handler for all configuration options properties | 
|  | * @method configOptions | 
|  | */ | 
|  | configOptions : function(type, args, obj) { | 
|  | this.Options[type.toUpperCase()] = args[0]; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The default handler for all configuration locale properties | 
|  | * @method configLocale | 
|  | */ | 
|  | configLocale : function(type, args, obj) { | 
|  | this.Locale[type.toUpperCase()] = args[0]; | 
|  |  | 
|  | this.cfg.refireEvent(DEF_CFG.LOCALE_MONTHS.key); | 
|  | this.cfg.refireEvent(DEF_CFG.LOCALE_WEEKDAYS.key); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The default handler for all configuration locale field length properties | 
|  | * @method configLocaleValues | 
|  | */ | 
|  | configLocaleValues : function(type, args, obj) { | 
|  |  | 
|  | type = type.toLowerCase(); | 
|  |  | 
|  | var val = args[0], | 
|  | cfg = this.cfg, | 
|  | Locale = this.Locale; | 
|  |  | 
|  | switch (type) { | 
|  | case DEF_CFG.LOCALE_MONTHS.key: | 
|  | switch (val) { | 
|  | case Calendar.SHORT: | 
|  | Locale.LOCALE_MONTHS = cfg.getProperty(DEF_CFG.MONTHS_SHORT.key).concat(); | 
|  | break; | 
|  | case Calendar.LONG: | 
|  | Locale.LOCALE_MONTHS = cfg.getProperty(DEF_CFG.MONTHS_LONG.key).concat(); | 
|  | break; | 
|  | } | 
|  | break; | 
|  | case DEF_CFG.LOCALE_WEEKDAYS.key: | 
|  | switch (val) { | 
|  | case Calendar.ONE_CHAR: | 
|  | Locale.LOCALE_WEEKDAYS = cfg.getProperty(DEF_CFG.WEEKDAYS_1CHAR.key).concat(); | 
|  | break; | 
|  | case Calendar.SHORT: | 
|  | Locale.LOCALE_WEEKDAYS = cfg.getProperty(DEF_CFG.WEEKDAYS_SHORT.key).concat(); | 
|  | break; | 
|  | case Calendar.MEDIUM: | 
|  | Locale.LOCALE_WEEKDAYS = cfg.getProperty(DEF_CFG.WEEKDAYS_MEDIUM.key).concat(); | 
|  | break; | 
|  | case Calendar.LONG: | 
|  | Locale.LOCALE_WEEKDAYS = cfg.getProperty(DEF_CFG.WEEKDAYS_LONG.key).concat(); | 
|  | break; | 
|  | } | 
|  |  | 
|  | var START_WEEKDAY = cfg.getProperty(DEF_CFG.START_WEEKDAY.key); | 
|  |  | 
|  | if (START_WEEKDAY > 0) { | 
|  | for (var w=0; w < START_WEEKDAY; ++w) { | 
|  | Locale.LOCALE_WEEKDAYS.push(Locale.LOCALE_WEEKDAYS.shift()); | 
|  | } | 
|  | } | 
|  | break; | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The default handler for the "navigator" property | 
|  | * @method configNavigator | 
|  | */ | 
|  | configNavigator : function(type, args, obj) { | 
|  | var val = args[0]; | 
|  | if (YAHOO.widget.CalendarNavigator && (val === true || Lang.isObject(val))) { | 
|  | if (!this.oNavigator) { | 
|  | this.oNavigator = new YAHOO.widget.CalendarNavigator(this); | 
|  | // Cleanup DOM Refs/Events before innerHTML is removed. | 
|  | this.beforeRenderEvent.subscribe(function () { | 
|  | if (!this.pages) { | 
|  | this.oNavigator.erase(); | 
|  | } | 
|  | }, this, true); | 
|  | } | 
|  | } else { | 
|  | if (this.oNavigator) { | 
|  | this.oNavigator.destroy(); | 
|  | this.oNavigator = null; | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Defines the style constants for the Calendar | 
|  | * @method initStyles | 
|  | */ | 
|  | initStyles : function() { | 
|  |  | 
|  | var defStyle = Calendar._STYLES; | 
|  |  | 
|  | this.Style = { | 
|  | /** | 
|  | * @property Style.CSS_ROW_HEADER | 
|  | */ | 
|  | CSS_ROW_HEADER: defStyle.CSS_ROW_HEADER, | 
|  | /** | 
|  | * @property Style.CSS_ROW_FOOTER | 
|  | */ | 
|  | CSS_ROW_FOOTER: defStyle.CSS_ROW_FOOTER, | 
|  | /** | 
|  | * @property Style.CSS_CELL | 
|  | */ | 
|  | CSS_CELL : defStyle.CSS_CELL, | 
|  | /** | 
|  | * @property Style.CSS_CELL_SELECTOR | 
|  | */ | 
|  | CSS_CELL_SELECTOR : defStyle.CSS_CELL_SELECTOR, | 
|  | /** | 
|  | * @property Style.CSS_CELL_SELECTED | 
|  | */ | 
|  | CSS_CELL_SELECTED : defStyle.CSS_CELL_SELECTED, | 
|  | /** | 
|  | * @property Style.CSS_CELL_SELECTABLE | 
|  | */ | 
|  | CSS_CELL_SELECTABLE : defStyle.CSS_CELL_SELECTABLE, | 
|  | /** | 
|  | * @property Style.CSS_CELL_RESTRICTED | 
|  | */ | 
|  | CSS_CELL_RESTRICTED : defStyle.CSS_CELL_RESTRICTED, | 
|  | /** | 
|  | * @property Style.CSS_CELL_TODAY | 
|  | */ | 
|  | CSS_CELL_TODAY : defStyle.CSS_CELL_TODAY, | 
|  | /** | 
|  | * @property Style.CSS_CELL_OOM | 
|  | */ | 
|  | CSS_CELL_OOM : defStyle.CSS_CELL_OOM, | 
|  | /** | 
|  | * @property Style.CSS_CELL_OOB | 
|  | */ | 
|  | CSS_CELL_OOB : defStyle.CSS_CELL_OOB, | 
|  | /** | 
|  | * @property Style.CSS_HEADER | 
|  | */ | 
|  | CSS_HEADER : defStyle.CSS_HEADER, | 
|  | /** | 
|  | * @property Style.CSS_HEADER_TEXT | 
|  | */ | 
|  | CSS_HEADER_TEXT : defStyle.CSS_HEADER_TEXT, | 
|  | /** | 
|  | * @property Style.CSS_BODY | 
|  | */ | 
|  | CSS_BODY : defStyle.CSS_BODY, | 
|  | /** | 
|  | * @property Style.CSS_WEEKDAY_CELL | 
|  | */ | 
|  | CSS_WEEKDAY_CELL : defStyle.CSS_WEEKDAY_CELL, | 
|  | /** | 
|  | * @property Style.CSS_WEEKDAY_ROW | 
|  | */ | 
|  | CSS_WEEKDAY_ROW : defStyle.CSS_WEEKDAY_ROW, | 
|  | /** | 
|  | * @property Style.CSS_FOOTER | 
|  | */ | 
|  | CSS_FOOTER : defStyle.CSS_FOOTER, | 
|  | /** | 
|  | * @property Style.CSS_CALENDAR | 
|  | */ | 
|  | CSS_CALENDAR : defStyle.CSS_CALENDAR, | 
|  | /** | 
|  | * @property Style.CSS_SINGLE | 
|  | */ | 
|  | CSS_SINGLE : defStyle.CSS_SINGLE, | 
|  | /** | 
|  | * @property Style.CSS_CONTAINER | 
|  | */ | 
|  | CSS_CONTAINER : defStyle.CSS_CONTAINER, | 
|  | /** | 
|  | * @property Style.CSS_NAV_LEFT | 
|  | */ | 
|  | CSS_NAV_LEFT : defStyle.CSS_NAV_LEFT, | 
|  | /** | 
|  | * @property Style.CSS_NAV_RIGHT | 
|  | */ | 
|  | CSS_NAV_RIGHT : defStyle.CSS_NAV_RIGHT, | 
|  | /** | 
|  | * @property Style.CSS_NAV | 
|  | */ | 
|  | CSS_NAV : defStyle.CSS_NAV, | 
|  | /** | 
|  | * @property Style.CSS_CLOSE | 
|  | */ | 
|  | CSS_CLOSE : defStyle.CSS_CLOSE, | 
|  | /** | 
|  | * @property Style.CSS_CELL_TOP | 
|  | */ | 
|  | CSS_CELL_TOP : defStyle.CSS_CELL_TOP, | 
|  | /** | 
|  | * @property Style.CSS_CELL_LEFT | 
|  | */ | 
|  | CSS_CELL_LEFT : defStyle.CSS_CELL_LEFT, | 
|  | /** | 
|  | * @property Style.CSS_CELL_RIGHT | 
|  | */ | 
|  | CSS_CELL_RIGHT : defStyle.CSS_CELL_RIGHT, | 
|  | /** | 
|  | * @property Style.CSS_CELL_BOTTOM | 
|  | */ | 
|  | CSS_CELL_BOTTOM : defStyle.CSS_CELL_BOTTOM, | 
|  | /** | 
|  | * @property Style.CSS_CELL_HOVER | 
|  | */ | 
|  | CSS_CELL_HOVER : defStyle.CSS_CELL_HOVER, | 
|  | /** | 
|  | * @property Style.CSS_CELL_HIGHLIGHT1 | 
|  | */ | 
|  | CSS_CELL_HIGHLIGHT1 : defStyle.CSS_CELL_HIGHLIGHT1, | 
|  | /** | 
|  | * @property Style.CSS_CELL_HIGHLIGHT2 | 
|  | */ | 
|  | CSS_CELL_HIGHLIGHT2 : defStyle.CSS_CELL_HIGHLIGHT2, | 
|  | /** | 
|  | * @property Style.CSS_CELL_HIGHLIGHT3 | 
|  | */ | 
|  | CSS_CELL_HIGHLIGHT3 : defStyle.CSS_CELL_HIGHLIGHT3, | 
|  | /** | 
|  | * @property Style.CSS_CELL_HIGHLIGHT4 | 
|  | */ | 
|  | CSS_CELL_HIGHLIGHT4 : defStyle.CSS_CELL_HIGHLIGHT4 | 
|  | }; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Builds the date label that will be displayed in the calendar header or | 
|  | * footer, depending on configuration. | 
|  | * @method buildMonthLabel | 
|  | * @return	{String}	The formatted calendar month label | 
|  | */ | 
|  | buildMonthLabel : function() { | 
|  | return this._buildMonthLabel(this.cfg.getProperty(DEF_CFG.PAGEDATE.key)); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Helper method, to format a Month Year string, given a JavaScript Date, based on the | 
|  | * Calendar localization settings | 
|  | * | 
|  | * @method _buildMonthLabel | 
|  | * @private | 
|  | * @param {Date} date | 
|  | * @return {String} Formated month, year string | 
|  | */ | 
|  | _buildMonthLabel : function(date) { | 
|  | var	monthLabel  = this.Locale.LOCALE_MONTHS[date.getMonth()] + this.Locale.MY_LABEL_MONTH_SUFFIX, | 
|  | yearLabel = date.getFullYear() + this.Locale.MY_LABEL_YEAR_SUFFIX; | 
|  |  | 
|  | if (this.Locale.MY_LABEL_MONTH_POSITION == 2 || this.Locale.MY_LABEL_YEAR_POSITION == 1) { | 
|  | return yearLabel + monthLabel; | 
|  | } else { | 
|  | return monthLabel + yearLabel; | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Builds the date digit that will be displayed in calendar cells | 
|  | * @method buildDayLabel | 
|  | * @param {Date}	workingDate	The current working date | 
|  | * @return	{String}	The formatted day label | 
|  | */ | 
|  | buildDayLabel : function(workingDate) { | 
|  | return workingDate.getDate(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Creates the title bar element and adds it to Calendar container DIV | 
|  | * | 
|  | * @method createTitleBar | 
|  | * @param {String} strTitle The title to display in the title bar | 
|  | * @return The title bar element | 
|  | */ | 
|  | createTitleBar : function(strTitle) { | 
|  | var tDiv = Dom.getElementsByClassName(YAHOO.widget.CalendarGroup.CSS_2UPTITLE, "div", this.oDomContainer)[0] || document.createElement("div"); | 
|  | tDiv.className = YAHOO.widget.CalendarGroup.CSS_2UPTITLE; | 
|  | tDiv.innerHTML = strTitle; | 
|  | this.oDomContainer.insertBefore(tDiv, this.oDomContainer.firstChild); | 
|  |  | 
|  | Dom.addClass(this.oDomContainer, "withtitle"); | 
|  |  | 
|  | return tDiv; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Removes the title bar element from the DOM | 
|  | * | 
|  | * @method removeTitleBar | 
|  | */ | 
|  | removeTitleBar : function() { | 
|  | var tDiv = Dom.getElementsByClassName(YAHOO.widget.CalendarGroup.CSS_2UPTITLE, "div", this.oDomContainer)[0] || null; | 
|  | if (tDiv) { | 
|  | Event.purgeElement(tDiv); | 
|  | this.oDomContainer.removeChild(tDiv); | 
|  | } | 
|  | Dom.removeClass(this.oDomContainer, "withtitle"); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Creates the close button HTML element and adds it to Calendar container DIV | 
|  | * | 
|  | * @method createCloseButton | 
|  | * @return The close HTML element created | 
|  | */ | 
|  | createCloseButton : function() { | 
|  | var cssClose = YAHOO.widget.CalendarGroup.CSS_2UPCLOSE, | 
|  | DEPR_CLOSE_PATH = "us/my/bn/x_d.gif", | 
|  | lnk = Dom.getElementsByClassName("link-close", "a", this.oDomContainer)[0], | 
|  | strings = this.cfg.getProperty(DEF_CFG.STRINGS.key), | 
|  | closeStr = (strings && strings.close) ? strings.close : ""; | 
|  |  | 
|  | if (!lnk) { | 
|  | lnk = document.createElement("a"); | 
|  | Event.addListener(lnk, "click", function(e, cal) { | 
|  | cal.hide(); | 
|  | Event.preventDefault(e); | 
|  | }, this); | 
|  | } | 
|  |  | 
|  | lnk.href = "#"; | 
|  | lnk.className = "link-close"; | 
|  |  | 
|  | if (Calendar.IMG_ROOT !== null) { | 
|  | var img = Dom.getElementsByClassName(cssClose, "img", lnk)[0] || document.createElement("img"); | 
|  | img.src = Calendar.IMG_ROOT + DEPR_CLOSE_PATH; | 
|  | img.className = cssClose; | 
|  | lnk.appendChild(img); | 
|  | } else { | 
|  | lnk.innerHTML = '<span class="' + cssClose + ' ' + this.Style.CSS_CLOSE + '">' + closeStr + '</span>'; | 
|  | } | 
|  | this.oDomContainer.appendChild(lnk); | 
|  |  | 
|  | return lnk; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Removes the close button HTML element from the DOM | 
|  | * | 
|  | * @method removeCloseButton | 
|  | */ | 
|  | removeCloseButton : function() { | 
|  | var btn = Dom.getElementsByClassName("link-close", "a", this.oDomContainer)[0] || null; | 
|  | if (btn) { | 
|  | Event.purgeElement(btn); | 
|  | this.oDomContainer.removeChild(btn); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders the calendar header. | 
|  | * @method renderHeader | 
|  | * @param {Array}	html	The current working HTML array | 
|  | * @return {Array} The current working HTML array | 
|  | */ | 
|  | renderHeader : function(html) { | 
|  |  | 
|  |  | 
|  | var colSpan = 7, | 
|  | DEPR_NAV_LEFT = "us/tr/callt.gif", | 
|  | DEPR_NAV_RIGHT = "us/tr/calrt.gif", | 
|  | cfg = this.cfg, | 
|  | pageDate = cfg.getProperty(DEF_CFG.PAGEDATE.key), | 
|  | strings= cfg.getProperty(DEF_CFG.STRINGS.key), | 
|  | prevStr = (strings && strings.previousMonth) ?  strings.previousMonth : "", | 
|  | nextStr = (strings && strings.nextMonth) ? strings.nextMonth : "", | 
|  | monthLabel; | 
|  |  | 
|  | if (cfg.getProperty(DEF_CFG.SHOW_WEEK_HEADER.key)) { | 
|  | colSpan += 1; | 
|  | } | 
|  |  | 
|  | if (cfg.getProperty(DEF_CFG.SHOW_WEEK_FOOTER.key)) { | 
|  | colSpan += 1; | 
|  | } | 
|  |  | 
|  | html[html.length] = "<thead>"; | 
|  | html[html.length] =		"<tr>"; | 
|  | html[html.length] =			'<th colspan="' + colSpan + '" class="' + this.Style.CSS_HEADER_TEXT + '">'; | 
|  | html[html.length] =				'<div class="' + this.Style.CSS_HEADER + '">'; | 
|  |  | 
|  | var renderLeft, renderRight = false; | 
|  |  | 
|  | if (this.parent) { | 
|  | if (this.index === 0) { | 
|  | renderLeft = true; | 
|  | } | 
|  | if (this.index == (this.parent.cfg.getProperty("pages") -1)) { | 
|  | renderRight = true; | 
|  | } | 
|  | } else { | 
|  | renderLeft = true; | 
|  | renderRight = true; | 
|  | } | 
|  |  | 
|  | if (renderLeft) { | 
|  | monthLabel  = this._buildMonthLabel(DateMath.subtract(pageDate, DateMath.MONTH, 1)); | 
|  |  | 
|  | var leftArrow = cfg.getProperty(DEF_CFG.NAV_ARROW_LEFT.key); | 
|  | // Check for deprecated customization - If someone set IMG_ROOT, but didn't set NAV_ARROW_LEFT, then set NAV_ARROW_LEFT to the old deprecated value | 
|  | if (leftArrow === null && Calendar.IMG_ROOT !== null) { | 
|  | leftArrow = Calendar.IMG_ROOT + DEPR_NAV_LEFT; | 
|  | } | 
|  | var leftStyle = (leftArrow === null) ? "" : ' style="background-image:url(' + leftArrow + ')"'; | 
|  | html[html.length] = '<a class="' + this.Style.CSS_NAV_LEFT + '"' + leftStyle + ' href="#">' + prevStr + ' (' + monthLabel + ')' + '</a>'; | 
|  | } | 
|  |  | 
|  | var lbl = this.buildMonthLabel(); | 
|  | var cal = this.parent || this; | 
|  | if (cal.cfg.getProperty("navigator")) { | 
|  | lbl = "<a class=\"" + this.Style.CSS_NAV + "\" href=\"#\">" + lbl + "</a>"; | 
|  | } | 
|  | html[html.length] = lbl; | 
|  |  | 
|  | if (renderRight) { | 
|  | monthLabel  = this._buildMonthLabel(DateMath.add(pageDate, DateMath.MONTH, 1)); | 
|  |  | 
|  | var rightArrow = cfg.getProperty(DEF_CFG.NAV_ARROW_RIGHT.key); | 
|  | if (rightArrow === null && Calendar.IMG_ROOT !== null) { | 
|  | rightArrow = Calendar.IMG_ROOT + DEPR_NAV_RIGHT; | 
|  | } | 
|  | var rightStyle = (rightArrow === null) ? "" : ' style="background-image:url(' + rightArrow + ')"'; | 
|  | html[html.length] = '<a class="' + this.Style.CSS_NAV_RIGHT + '"' + rightStyle + ' href="#">' + nextStr + ' (' + monthLabel + ')' + '</a>'; | 
|  | } | 
|  |  | 
|  | html[html.length] =	'</div>\n</th>\n</tr>'; | 
|  |  | 
|  | if (cfg.getProperty(DEF_CFG.SHOW_WEEKDAYS.key)) { | 
|  | html = this.buildWeekdays(html); | 
|  | } | 
|  |  | 
|  | html[html.length] = '</thead>'; | 
|  |  | 
|  | return html; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders the Calendar's weekday headers. | 
|  | * @method buildWeekdays | 
|  | * @param {Array}	html	The current working HTML array | 
|  | * @return {Array} The current working HTML array | 
|  | */ | 
|  | buildWeekdays : function(html) { | 
|  |  | 
|  | html[html.length] = '<tr class="' + this.Style.CSS_WEEKDAY_ROW + '">'; | 
|  |  | 
|  | if (this.cfg.getProperty(DEF_CFG.SHOW_WEEK_HEADER.key)) { | 
|  | html[html.length] = '<th> </th>'; | 
|  | } | 
|  |  | 
|  | for(var i=0;i < this.Locale.LOCALE_WEEKDAYS.length; ++i) { | 
|  | html[html.length] = '<th class="calweekdaycell">' + this.Locale.LOCALE_WEEKDAYS[i] + '</th>'; | 
|  | } | 
|  |  | 
|  | if (this.cfg.getProperty(DEF_CFG.SHOW_WEEK_FOOTER.key)) { | 
|  | html[html.length] = '<th> </th>'; | 
|  | } | 
|  |  | 
|  | html[html.length] = '</tr>'; | 
|  |  | 
|  | return html; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders the calendar body. | 
|  | * @method renderBody | 
|  | * @param {Date}	workingDate	The current working Date being used for the render process | 
|  | * @param {Array}	html	The current working HTML array | 
|  | * @return {Array} The current working HTML array | 
|  | */ | 
|  | renderBody : function(workingDate, html) { | 
|  |  | 
|  | var startDay = this.cfg.getProperty(DEF_CFG.START_WEEKDAY.key); | 
|  |  | 
|  | this.preMonthDays = workingDate.getDay(); | 
|  | if (startDay > 0) { | 
|  | this.preMonthDays -= startDay; | 
|  | } | 
|  | if (this.preMonthDays < 0) { | 
|  | this.preMonthDays += 7; | 
|  | } | 
|  |  | 
|  | this.monthDays = DateMath.findMonthEnd(workingDate).getDate(); | 
|  | this.postMonthDays = Calendar.DISPLAY_DAYS-this.preMonthDays-this.monthDays; | 
|  |  | 
|  |  | 
|  | workingDate = DateMath.subtract(workingDate, DateMath.DAY, this.preMonthDays); | 
|  |  | 
|  | var weekNum, | 
|  | weekClass, | 
|  | weekPrefix = "w", | 
|  | cellPrefix = "_cell", | 
|  | workingDayPrefix = "wd", | 
|  | dayPrefix = "d", | 
|  | cellRenderers, | 
|  | renderer, | 
|  | t = this.today, | 
|  | cfg = this.cfg, | 
|  | todayYear = t.getFullYear(), | 
|  | todayMonth = t.getMonth(), | 
|  | todayDate = t.getDate(), | 
|  | useDate = cfg.getProperty(DEF_CFG.PAGEDATE.key), | 
|  | hideBlankWeeks = cfg.getProperty(DEF_CFG.HIDE_BLANK_WEEKS.key), | 
|  | showWeekFooter = cfg.getProperty(DEF_CFG.SHOW_WEEK_FOOTER.key), | 
|  | showWeekHeader = cfg.getProperty(DEF_CFG.SHOW_WEEK_HEADER.key), | 
|  | mindate = cfg.getProperty(DEF_CFG.MINDATE.key), | 
|  | maxdate = cfg.getProperty(DEF_CFG.MAXDATE.key); | 
|  |  | 
|  | if (mindate) { | 
|  | mindate = DateMath.clearTime(mindate); | 
|  | } | 
|  | if (maxdate) { | 
|  | maxdate = DateMath.clearTime(maxdate); | 
|  | } | 
|  |  | 
|  | html[html.length] = '<tbody class="m' + (useDate.getMonth()+1) + ' ' + this.Style.CSS_BODY + '">'; | 
|  |  | 
|  | var i = 0, | 
|  | tempDiv = document.createElement("div"), | 
|  | cell = document.createElement("td"); | 
|  |  | 
|  | tempDiv.appendChild(cell); | 
|  |  | 
|  | var cal = this.parent || this; | 
|  |  | 
|  | for (var r=0;r<6;r++) { | 
|  | weekNum = DateMath.getWeekNumber(workingDate, startDay); | 
|  | weekClass = weekPrefix + weekNum; | 
|  |  | 
|  | // Local OOM check for performance, since we already have pagedate | 
|  | if (r !== 0 && hideBlankWeeks === true && workingDate.getMonth() != useDate.getMonth()) { | 
|  | break; | 
|  | } else { | 
|  | html[html.length] = '<tr class="' + weekClass + '">'; | 
|  |  | 
|  | if (showWeekHeader) { html = this.renderRowHeader(weekNum, html); } | 
|  |  | 
|  | for (var d=0; d < 7; d++){ // Render actual days | 
|  |  | 
|  | cellRenderers = []; | 
|  |  | 
|  | this.clearElement(cell); | 
|  | cell.className = this.Style.CSS_CELL; | 
|  | cell.id = this.id + cellPrefix + i; | 
|  |  | 
|  | if (workingDate.getDate()		== todayDate && | 
|  | workingDate.getMonth()		== todayMonth && | 
|  | workingDate.getFullYear()	== todayYear) { | 
|  | cellRenderers[cellRenderers.length]=cal.renderCellStyleToday; | 
|  | } | 
|  |  | 
|  | var workingArray = [workingDate.getFullYear(),workingDate.getMonth()+1,workingDate.getDate()]; | 
|  | this.cellDates[this.cellDates.length] = workingArray; // Add this date to cellDates | 
|  |  | 
|  | // Local OOM check for performance, since we already have pagedate | 
|  | if (workingDate.getMonth() != useDate.getMonth()) { | 
|  | cellRenderers[cellRenderers.length]=cal.renderCellNotThisMonth; | 
|  | } else { | 
|  | Dom.addClass(cell, workingDayPrefix + workingDate.getDay()); | 
|  | Dom.addClass(cell, dayPrefix + workingDate.getDate()); | 
|  |  | 
|  | for (var s=0;s<this.renderStack.length;++s) { | 
|  |  | 
|  | renderer = null; | 
|  |  | 
|  | var rArray = this.renderStack[s], | 
|  | type = rArray[0], | 
|  | month, | 
|  | day, | 
|  | year; | 
|  |  | 
|  | switch (type) { | 
|  | case Calendar.DATE: | 
|  | month = rArray[1][1]; | 
|  | day = rArray[1][2]; | 
|  | year = rArray[1][0]; | 
|  |  | 
|  | if (workingDate.getMonth()+1 == month && workingDate.getDate() == day && workingDate.getFullYear() == year) { | 
|  | renderer = rArray[2]; | 
|  | this.renderStack.splice(s,1); | 
|  | } | 
|  | break; | 
|  | case Calendar.MONTH_DAY: | 
|  | month = rArray[1][0]; | 
|  | day = rArray[1][1]; | 
|  |  | 
|  | if (workingDate.getMonth()+1 == month && workingDate.getDate() == day) { | 
|  | renderer = rArray[2]; | 
|  | this.renderStack.splice(s,1); | 
|  | } | 
|  | break; | 
|  | case Calendar.RANGE: | 
|  | var date1 = rArray[1][0], | 
|  | date2 = rArray[1][1], | 
|  | d1month = date1[1], | 
|  | d1day = date1[2], | 
|  | d1year = date1[0], | 
|  | d1 = DateMath.getDate(d1year, d1month-1, d1day), | 
|  | d2month = date2[1], | 
|  | d2day = date2[2], | 
|  | d2year = date2[0], | 
|  | d2 = DateMath.getDate(d2year, d2month-1, d2day); | 
|  |  | 
|  | if (workingDate.getTime() >= d1.getTime() && workingDate.getTime() <= d2.getTime()) { | 
|  | renderer = rArray[2]; | 
|  |  | 
|  | if (workingDate.getTime()==d2.getTime()) { | 
|  | this.renderStack.splice(s,1); | 
|  | } | 
|  | } | 
|  | break; | 
|  | case Calendar.WEEKDAY: | 
|  | var weekday = rArray[1][0]; | 
|  | if (workingDate.getDay()+1 == weekday) { | 
|  | renderer = rArray[2]; | 
|  | } | 
|  | break; | 
|  | case Calendar.MONTH: | 
|  | month = rArray[1][0]; | 
|  | if (workingDate.getMonth()+1 == month) { | 
|  | renderer = rArray[2]; | 
|  | } | 
|  | break; | 
|  | } | 
|  |  | 
|  | if (renderer) { | 
|  | cellRenderers[cellRenderers.length]=renderer; | 
|  | } | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | if (this._indexOfSelectedFieldArray(workingArray) > -1) { | 
|  | cellRenderers[cellRenderers.length]=cal.renderCellStyleSelected; | 
|  | } | 
|  |  | 
|  | if ((mindate && (workingDate.getTime() < mindate.getTime())) || | 
|  | (maxdate && (workingDate.getTime() > maxdate.getTime())) | 
|  | ) { | 
|  | cellRenderers[cellRenderers.length]=cal.renderOutOfBoundsDate; | 
|  | } else { | 
|  | cellRenderers[cellRenderers.length]=cal.styleCellDefault; | 
|  | cellRenderers[cellRenderers.length]=cal.renderCellDefault; | 
|  | } | 
|  |  | 
|  | for (var x=0; x < cellRenderers.length; ++x) { | 
|  | if (cellRenderers[x].call(cal, workingDate, cell) == Calendar.STOP_RENDER) { | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | workingDate.setTime(workingDate.getTime() + DateMath.ONE_DAY_MS); | 
|  | // Just in case we crossed DST/Summertime boundaries | 
|  | workingDate = DateMath.clearTime(workingDate); | 
|  |  | 
|  | if (i >= 0 && i <= 6) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_TOP); | 
|  | } | 
|  | if ((i % 7) === 0) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_LEFT); | 
|  | } | 
|  | if (((i+1) % 7) === 0) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_RIGHT); | 
|  | } | 
|  |  | 
|  | var postDays = this.postMonthDays; | 
|  | if (hideBlankWeeks && postDays >= 7) { | 
|  | var blankWeeks = Math.floor(postDays/7); | 
|  | for (var p=0;p<blankWeeks;++p) { | 
|  | postDays -= 7; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (i >= ((this.preMonthDays+postDays+this.monthDays)-7)) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_BOTTOM); | 
|  | } | 
|  |  | 
|  | html[html.length] = tempDiv.innerHTML; | 
|  | i++; | 
|  | } | 
|  |  | 
|  | if (showWeekFooter) { html = this.renderRowFooter(weekNum, html); } | 
|  |  | 
|  | html[html.length] = '</tr>'; | 
|  | } | 
|  | } | 
|  |  | 
|  | html[html.length] = '</tbody>'; | 
|  |  | 
|  | return html; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders the calendar footer. In the default implementation, there is | 
|  | * no footer. | 
|  | * @method renderFooter | 
|  | * @param {Array}	html	The current working HTML array | 
|  | * @return {Array} The current working HTML array | 
|  | */ | 
|  | renderFooter : function(html) { return html; }, | 
|  |  | 
|  | /** | 
|  | * Renders the calendar after it has been configured. The render() method has a specific call chain that will execute | 
|  | * when the method is called: renderHeader, renderBody, renderFooter. | 
|  | * Refer to the documentation for those methods for information on | 
|  | * individual render tasks. | 
|  | * @method render | 
|  | */ | 
|  | render : function() { | 
|  | this.beforeRenderEvent.fire(); | 
|  |  | 
|  | // Find starting day of the current month | 
|  | var workingDate = DateMath.findMonthStart(this.cfg.getProperty(DEF_CFG.PAGEDATE.key)); | 
|  |  | 
|  | this.resetRenderers(); | 
|  | this.cellDates.length = 0; | 
|  |  | 
|  | Event.purgeElement(this.oDomContainer, true); | 
|  |  | 
|  | var html = []; | 
|  |  | 
|  | html[html.length] = '<table cellSpacing="0" class="' + this.Style.CSS_CALENDAR + ' y' + workingDate.getFullYear() + '" id="' + this.id + '">'; | 
|  | html = this.renderHeader(html); | 
|  | html = this.renderBody(workingDate, html); | 
|  | html = this.renderFooter(html); | 
|  | html[html.length] = '</table>'; | 
|  |  | 
|  | this.oDomContainer.innerHTML = html.join("\n"); | 
|  |  | 
|  | this.applyListeners(); | 
|  | this.cells = this.oDomContainer.getElementsByTagName("td"); | 
|  |  | 
|  | this.cfg.refireEvent(DEF_CFG.TITLE.key); | 
|  | this.cfg.refireEvent(DEF_CFG.CLOSE.key); | 
|  | this.cfg.refireEvent(DEF_CFG.IFRAME.key); | 
|  |  | 
|  | this.renderEvent.fire(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Applies the Calendar's DOM listeners to applicable elements. | 
|  | * @method applyListeners | 
|  | */ | 
|  | applyListeners : function() { | 
|  | var root = this.oDomContainer, | 
|  | cal = this.parent || this, | 
|  | anchor = "a", | 
|  | click = "click"; | 
|  |  | 
|  | var linkLeft = Dom.getElementsByClassName(this.Style.CSS_NAV_LEFT, anchor, root), | 
|  | linkRight = Dom.getElementsByClassName(this.Style.CSS_NAV_RIGHT, anchor, root); | 
|  |  | 
|  | if (linkLeft && linkLeft.length > 0) { | 
|  | this.linkLeft = linkLeft[0]; | 
|  | Event.addListener(this.linkLeft, click, this.doPreviousMonthNav, cal, true); | 
|  | } | 
|  |  | 
|  | if (linkRight && linkRight.length > 0) { | 
|  | this.linkRight = linkRight[0]; | 
|  | Event.addListener(this.linkRight, click, this.doNextMonthNav, cal, true); | 
|  | } | 
|  |  | 
|  | if (cal.cfg.getProperty("navigator") !== null) { | 
|  | this.applyNavListeners(); | 
|  | } | 
|  |  | 
|  | if (this.domEventMap) { | 
|  | var el,elements; | 
|  | for (var cls in this.domEventMap) { | 
|  | if (Lang.hasOwnProperty(this.domEventMap, cls)) { | 
|  | var items = this.domEventMap[cls]; | 
|  |  | 
|  | if (! (items instanceof Array)) { | 
|  | items = [items]; | 
|  | } | 
|  |  | 
|  | for (var i=0;i<items.length;i++)	{ | 
|  | var item = items[i]; | 
|  | elements = Dom.getElementsByClassName(cls, item.tag, this.oDomContainer); | 
|  |  | 
|  | for (var c=0;c<elements.length;c++) { | 
|  | el = elements[c]; | 
|  | Event.addListener(el, item.event, item.handler, item.scope, item.correct ); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | Event.addListener(this.oDomContainer, "click", this.doSelectCell, this); | 
|  | Event.addListener(this.oDomContainer, "mouseover", this.doCellMouseOver, this); | 
|  | Event.addListener(this.oDomContainer, "mouseout", this.doCellMouseOut, this); | 
|  | }, | 
|  |  | 
|  | applyNavListeners : function() { | 
|  | var calParent = this.parent || this, | 
|  | cal = this, | 
|  | navBtns = Dom.getElementsByClassName(this.Style.CSS_NAV, "a", this.oDomContainer); | 
|  |  | 
|  | if (navBtns.length > 0) { | 
|  |  | 
|  | Event.addListener(navBtns, "click", function (e, obj) { | 
|  | var target = Event.getTarget(e); | 
|  | // this == navBtn | 
|  | if (this === target || Dom.isAncestor(this, target)) { | 
|  | Event.preventDefault(e); | 
|  | } | 
|  | var navigator = calParent.oNavigator; | 
|  | if (navigator) { | 
|  | var pgdate = cal.cfg.getProperty("pagedate"); | 
|  | navigator.setYear(pgdate.getFullYear()); | 
|  | navigator.setMonth(pgdate.getMonth()); | 
|  | navigator.show(); | 
|  | } | 
|  | }); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Retrieves the Date object for the specified Calendar cell | 
|  | * @method getDateByCellId | 
|  | * @param {String}	id	The id of the cell | 
|  | * @return {Date} The Date object for the specified Calendar cell | 
|  | */ | 
|  | getDateByCellId : function(id) { | 
|  | var date = this.getDateFieldsByCellId(id); | 
|  | return (date) ? DateMath.getDate(date[0],date[1]-1,date[2]) : null; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Retrieves the Date object for the specified Calendar cell | 
|  | * @method getDateFieldsByCellId | 
|  | * @param {String}	id	The id of the cell | 
|  | * @return {Array}	The array of Date fields for the specified Calendar cell | 
|  | */ | 
|  | getDateFieldsByCellId : function(id) { | 
|  | id = this.getIndexFromId(id); | 
|  | return (id > -1) ? this.cellDates[id] : null; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Find the Calendar's cell index for a given date. | 
|  | * If the date is not found, the method returns -1. | 
|  | * <p> | 
|  | * The returned index can be used to lookup the cell HTMLElement | 
|  | * using the Calendar's cells array or passed to selectCell to select | 
|  | * cells by index. | 
|  | * </p> | 
|  | * | 
|  | * See <a href="#cells">cells</a>, <a href="#selectCell">selectCell</a>. | 
|  | * | 
|  | * @method getCellIndex | 
|  | * @param {Date} date JavaScript Date object, for which to find a cell index. | 
|  | * @return {Number} The index of the date in Calendars cellDates/cells arrays, or -1 if the date | 
|  | * is not on the curently rendered Calendar page. | 
|  | */ | 
|  | getCellIndex : function(date) { | 
|  | var idx = -1; | 
|  | if (date) { | 
|  | var m = date.getMonth(), | 
|  | y = date.getFullYear(), | 
|  | d = date.getDate(), | 
|  | dates = this.cellDates; | 
|  |  | 
|  | for (var i = 0; i < dates.length; ++i) { | 
|  | var cellDate = dates[i]; | 
|  | if (cellDate[0] === y && cellDate[1] === m+1 && cellDate[2] === d) { | 
|  | idx = i; | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | return idx; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Given the id used to mark each Calendar cell, this method | 
|  | * extracts the index number from the id. | 
|  | * | 
|  | * @param {String} strId The cell id | 
|  | * @return {Number} The index of the cell, or -1 if id does not contain an index number | 
|  | */ | 
|  | getIndexFromId : function(strId) { | 
|  | var idx = -1, | 
|  | li = strId.lastIndexOf("_cell"); | 
|  |  | 
|  | if (li > -1) { | 
|  | idx = parseInt(strId.substring(li + 5), 10); | 
|  | } | 
|  |  | 
|  | return idx; | 
|  | }, | 
|  |  | 
|  | // BEGIN BUILT-IN TABLE CELL RENDERERS | 
|  |  | 
|  | /** | 
|  | * Renders a cell that falls before the minimum date or after the maximum date. | 
|  | * widget class. | 
|  | * @method renderOutOfBoundsDate | 
|  | * @param {Date}					workingDate		The current working Date object being used to generate the calendar | 
|  | * @param {HTMLTableCellElement}	cell			The current working cell in the calendar | 
|  | * @return {String} YAHOO.widget.Calendar.STOP_RENDER if rendering should stop with this style, null or nothing if rendering | 
|  | *			should not be terminated | 
|  | */ | 
|  | renderOutOfBoundsDate : function(workingDate, cell) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_OOB); | 
|  | cell.innerHTML = workingDate.getDate(); | 
|  | return Calendar.STOP_RENDER; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders the row header for a week. | 
|  | * @method renderRowHeader | 
|  | * @param {Number}	weekNum	The week number of the current row | 
|  | * @param {Array}	cell	The current working HTML array | 
|  | */ | 
|  | renderRowHeader : function(weekNum, html) { | 
|  | html[html.length] = '<th class="calrowhead">' + weekNum + '</th>'; | 
|  | return html; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders the row footer for a week. | 
|  | * @method renderRowFooter | 
|  | * @param {Number}	weekNum	The week number of the current row | 
|  | * @param {Array}	cell	The current working HTML array | 
|  | */ | 
|  | renderRowFooter : function(weekNum, html) { | 
|  | html[html.length] = '<th class="calrowfoot">' + weekNum + '</th>'; | 
|  | return html; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders a single standard calendar cell in the calendar widget table. | 
|  | * All logic for determining how a standard default cell will be rendered is | 
|  | * encapsulated in this method, and must be accounted for when extending the | 
|  | * widget class. | 
|  | * @method renderCellDefault | 
|  | * @param {Date}					workingDate		The current working Date object being used to generate the calendar | 
|  | * @param {HTMLTableCellElement}	cell			The current working cell in the calendar | 
|  | */ | 
|  | renderCellDefault : function(workingDate, cell) { | 
|  | cell.innerHTML = '<a href="#" class="' + this.Style.CSS_CELL_SELECTOR + '">' + this.buildDayLabel(workingDate) + "</a>"; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Styles a selectable cell. | 
|  | * @method styleCellDefault | 
|  | * @param {Date}					workingDate		The current working Date object being used to generate the calendar | 
|  | * @param {HTMLTableCellElement}	cell			The current working cell in the calendar | 
|  | */ | 
|  | styleCellDefault : function(workingDate, cell) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_SELECTABLE); | 
|  | }, | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Renders a single standard calendar cell using the CSS hightlight1 style | 
|  | * @method renderCellStyleHighlight1 | 
|  | * @param {Date}					workingDate		The current working Date object being used to generate the calendar | 
|  | * @param {HTMLTableCellElement}	cell			The current working cell in the calendar | 
|  | */ | 
|  | renderCellStyleHighlight1 : function(workingDate, cell) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT1); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders a single standard calendar cell using the CSS hightlight2 style | 
|  | * @method renderCellStyleHighlight2 | 
|  | * @param {Date}					workingDate		The current working Date object being used to generate the calendar | 
|  | * @param {HTMLTableCellElement}	cell			The current working cell in the calendar | 
|  | */ | 
|  | renderCellStyleHighlight2 : function(workingDate, cell) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT2); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders a single standard calendar cell using the CSS hightlight3 style | 
|  | * @method renderCellStyleHighlight3 | 
|  | * @param {Date}					workingDate		The current working Date object being used to generate the calendar | 
|  | * @param {HTMLTableCellElement}	cell			The current working cell in the calendar | 
|  | */ | 
|  | renderCellStyleHighlight3 : function(workingDate, cell) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT3); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders a single standard calendar cell using the CSS hightlight4 style | 
|  | * @method renderCellStyleHighlight4 | 
|  | * @param {Date}					workingDate		The current working Date object being used to generate the calendar | 
|  | * @param {HTMLTableCellElement}	cell			The current working cell in the calendar | 
|  | */ | 
|  | renderCellStyleHighlight4 : function(workingDate, cell) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT4); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Applies the default style used for rendering today's date to the current calendar cell | 
|  | * @method renderCellStyleToday | 
|  | * @param {Date}					workingDate		The current working Date object being used to generate the calendar | 
|  | * @param {HTMLTableCellElement}	cell			The current working cell in the calendar | 
|  | */ | 
|  | renderCellStyleToday : function(workingDate, cell) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_TODAY); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Applies the default style used for rendering selected dates to the current calendar cell | 
|  | * @method renderCellStyleSelected | 
|  | * @param {Date}					workingDate		The current working Date object being used to generate the calendar | 
|  | * @param {HTMLTableCellElement}	cell			The current working cell in the calendar | 
|  | * @return {String} YAHOO.widget.Calendar.STOP_RENDER if rendering should stop with this style, null or nothing if rendering | 
|  | *			should not be terminated | 
|  | */ | 
|  | renderCellStyleSelected : function(workingDate, cell) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_SELECTED); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Applies the default style used for rendering dates that are not a part of the current | 
|  | * month (preceding or trailing the cells for the current month) | 
|  | * @method renderCellNotThisMonth | 
|  | * @param {Date}					workingDate		The current working Date object being used to generate the calendar | 
|  | * @param {HTMLTableCellElement}	cell			The current working cell in the calendar | 
|  | * @return {String} YAHOO.widget.Calendar.STOP_RENDER if rendering should stop with this style, null or nothing if rendering | 
|  | *			should not be terminated | 
|  | */ | 
|  | renderCellNotThisMonth : function(workingDate, cell) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_OOM); | 
|  | cell.innerHTML=workingDate.getDate(); | 
|  | return Calendar.STOP_RENDER; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders the current calendar cell as a non-selectable "black-out" date using the default | 
|  | * restricted style. | 
|  | * @method renderBodyCellRestricted | 
|  | * @param {Date}					workingDate		The current working Date object being used to generate the calendar | 
|  | * @param {HTMLTableCellElement}	cell			The current working cell in the calendar | 
|  | * @return {String} YAHOO.widget.Calendar.STOP_RENDER if rendering should stop with this style, null or nothing if rendering | 
|  | *			should not be terminated | 
|  | */ | 
|  | renderBodyCellRestricted : function(workingDate, cell) { | 
|  | Dom.addClass(cell, this.Style.CSS_CELL); | 
|  | Dom.addClass(cell, this.Style.CSS_CELL_RESTRICTED); | 
|  | cell.innerHTML=workingDate.getDate(); | 
|  | return Calendar.STOP_RENDER; | 
|  | }, | 
|  |  | 
|  | // END BUILT-IN TABLE CELL RENDERERS | 
|  |  | 
|  | // BEGIN MONTH NAVIGATION METHODS | 
|  |  | 
|  | /** | 
|  | * 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) { | 
|  | var cfgPageDate = DEF_CFG.PAGEDATE.key; | 
|  | this.cfg.setProperty(cfgPageDate, DateMath.add(this.cfg.getProperty(cfgPageDate), DateMath.MONTH, count)); | 
|  | this.resetRenderers(); | 
|  | this.changePageEvent.fire(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * 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) { | 
|  | var cfgPageDate = DEF_CFG.PAGEDATE.key; | 
|  | this.cfg.setProperty(cfgPageDate, DateMath.subtract(this.cfg.getProperty(cfgPageDate), DateMath.MONTH, count)); | 
|  | this.resetRenderers(); | 
|  | this.changePageEvent.fire(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * 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) { | 
|  | var cfgPageDate = DEF_CFG.PAGEDATE.key; | 
|  | this.cfg.setProperty(cfgPageDate, DateMath.add(this.cfg.getProperty(cfgPageDate), DateMath.YEAR, count)); | 
|  | this.resetRenderers(); | 
|  | this.changePageEvent.fire(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * 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) { | 
|  | var cfgPageDate = DEF_CFG.PAGEDATE.key; | 
|  | this.cfg.setProperty(cfgPageDate, DateMath.subtract(this.cfg.getProperty(cfgPageDate), DateMath.YEAR, count)); | 
|  | this.resetRenderers(); | 
|  | this.changePageEvent.fire(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Navigates to the next month page in the calendar widget. | 
|  | * @method nextMonth | 
|  | */ | 
|  | nextMonth : function() { | 
|  | this.addMonths(1); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Navigates to the previous month page in the calendar widget. | 
|  | * @method previousMonth | 
|  | */ | 
|  | previousMonth : function() { | 
|  | this.subtractMonths(1); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Navigates to the next year in the currently selected month in the calendar widget. | 
|  | * @method nextYear | 
|  | */ | 
|  | nextYear : function() { | 
|  | this.addYears(1); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Navigates to the previous year in the currently selected month in the calendar widget. | 
|  | * @method previousYear | 
|  | */ | 
|  | previousYear : function() { | 
|  | this.subtractYears(1); | 
|  | }, | 
|  |  | 
|  | // END MONTH NAVIGATION METHODS | 
|  |  | 
|  | // BEGIN SELECTION METHODS | 
|  |  | 
|  | /** | 
|  | * Resets the calendar widget to the originally selected month and year, and | 
|  | * sets the calendar to the initial selection(s). | 
|  | * @method reset | 
|  | */ | 
|  | reset : function() { | 
|  | this.cfg.resetProperty(DEF_CFG.SELECTED.key); | 
|  | this.cfg.resetProperty(DEF_CFG.PAGEDATE.key); | 
|  | this.resetEvent.fire(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Clears the selected dates in the current calendar widget and sets the calendar | 
|  | * to the current month and year. | 
|  | * @method clear | 
|  | */ | 
|  | clear : function() { | 
|  | this.cfg.setProperty(DEF_CFG.SELECTED.key, []); | 
|  | this.cfg.setProperty(DEF_CFG.PAGEDATE.key, new Date(this.today.getTime())); | 
|  | this.clearEvent.fire(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * 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. | 
|  | * | 
|  | * Any dates which are OOB (out of bounds, not selectable) will not be selected and the array of | 
|  | * selected dates passed to the selectEvent will not contain OOB dates. | 
|  | * | 
|  | * If all dates are OOB, the no state change will occur; beforeSelect and select events will not be fired. | 
|  | * | 
|  | * @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) { | 
|  |  | 
|  | var aToBeSelected = this._toFieldArray(date), | 
|  | validDates = [], | 
|  | selected = [], | 
|  | cfgSelected = DEF_CFG.SELECTED.key; | 
|  |  | 
|  |  | 
|  | for (var a=0; a < aToBeSelected.length; ++a) { | 
|  | var toSelect = aToBeSelected[a]; | 
|  |  | 
|  | if (!this.isDateOOB(this._toDate(toSelect))) { | 
|  |  | 
|  | if (validDates.length === 0) { | 
|  | this.beforeSelectEvent.fire(); | 
|  | selected = this.cfg.getProperty(cfgSelected); | 
|  | } | 
|  | validDates.push(toSelect); | 
|  |  | 
|  | if (this._indexOfSelectedFieldArray(toSelect) == -1) { | 
|  | selected[selected.length] = toSelect; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | if (validDates.length > 0) { | 
|  | if (this.parent) { | 
|  | this.parent.cfg.setProperty(cfgSelected, selected); | 
|  | } else { | 
|  | this.cfg.setProperty(cfgSelected, selected); | 
|  | } | 
|  | this.selectEvent.fire(validDates); | 
|  | } | 
|  |  | 
|  | return this.getSelectedDates(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Selects a date on the current calendar by referencing the index of the cell that should be selected. | 
|  | * This method is used to easily select a single cell (usually with a mouse click) without having to do | 
|  | * a full render. The selected style is applied to the cell directly. | 
|  | * | 
|  | * If the cell is not marked with the CSS_CELL_SELECTABLE class (as is the case by default for out of month | 
|  | * or out of bounds cells), it will not be selected and in such a case beforeSelect and select events will not be fired. | 
|  | * | 
|  | * @method selectCell | 
|  | * @param	{Number}	cellIndex	The index of the cell to select in the current calendar. | 
|  | * @return	{Date[]}	Array of JavaScript Date objects representing all individual dates that are currently selected. | 
|  | */ | 
|  | selectCell : function(cellIndex) { | 
|  |  | 
|  | var cell = this.cells[cellIndex], | 
|  | cellDate = this.cellDates[cellIndex], | 
|  | dCellDate = this._toDate(cellDate), | 
|  | selectable = Dom.hasClass(cell, this.Style.CSS_CELL_SELECTABLE); | 
|  |  | 
|  |  | 
|  | if (selectable) { | 
|  |  | 
|  | this.beforeSelectEvent.fire(); | 
|  |  | 
|  | var cfgSelected = DEF_CFG.SELECTED.key; | 
|  | var selected = this.cfg.getProperty(cfgSelected); | 
|  |  | 
|  | var selectDate = cellDate.concat(); | 
|  |  | 
|  | if (this._indexOfSelectedFieldArray(selectDate) == -1) { | 
|  | selected[selected.length] = selectDate; | 
|  | } | 
|  | if (this.parent) { | 
|  | this.parent.cfg.setProperty(cfgSelected, selected); | 
|  | } else { | 
|  | this.cfg.setProperty(cfgSelected, selected); | 
|  | } | 
|  | this.renderCellStyleSelected(dCellDate,cell); | 
|  | this.selectEvent.fire([selectDate]); | 
|  |  | 
|  | this.doCellMouseOut.call(cell, null, this); | 
|  | } | 
|  |  | 
|  | 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. | 
|  | * | 
|  | * The method will not attempt to deselect any dates which are OOB (out of bounds, and hence not selectable) | 
|  | * and the array of deselected dates passed to the deselectEvent will not contain any OOB dates. | 
|  | * | 
|  | * If all dates are OOB, beforeDeselect and deselect events will not be fired. | 
|  | * | 
|  | * @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) { | 
|  |  | 
|  | var aToBeDeselected = this._toFieldArray(date), | 
|  | validDates = [], | 
|  | selected = [], | 
|  | cfgSelected = DEF_CFG.SELECTED.key; | 
|  |  | 
|  |  | 
|  | for (var a=0; a < aToBeDeselected.length; ++a) { | 
|  | var toDeselect = aToBeDeselected[a]; | 
|  |  | 
|  | if (!this.isDateOOB(this._toDate(toDeselect))) { | 
|  |  | 
|  | if (validDates.length === 0) { | 
|  | this.beforeDeselectEvent.fire(); | 
|  | selected = this.cfg.getProperty(cfgSelected); | 
|  | } | 
|  |  | 
|  | validDates.push(toDeselect); | 
|  |  | 
|  | var index = this._indexOfSelectedFieldArray(toDeselect); | 
|  | if (index != -1) { | 
|  | selected.splice(index,1); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | if (validDates.length > 0) { | 
|  | if (this.parent) { | 
|  | this.parent.cfg.setProperty(cfgSelected, selected); | 
|  | } else { | 
|  | this.cfg.setProperty(cfgSelected, selected); | 
|  | } | 
|  | this.deselectEvent.fire(validDates); | 
|  | } | 
|  |  | 
|  | return this.getSelectedDates(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Deselects a date on the current calendar by referencing the index of the cell that should be deselected. | 
|  | * This method is used to easily deselect a single cell (usually with a mouse click) without having to do | 
|  | * a full render. The selected style is removed from the cell directly. | 
|  | * | 
|  | * If the cell is not marked with the CSS_CELL_SELECTABLE class (as is the case by default for out of month | 
|  | * or out of bounds cells), the method will not attempt to deselect it and in such a case, beforeDeselect and | 
|  | * deselect events will not be fired. | 
|  | * | 
|  | * @method deselectCell | 
|  | * @param	{Number}	cellIndex	The index of the cell to deselect in the current calendar. | 
|  | * @return	{Date[]}	Array of JavaScript Date objects representing all individual dates that are currently selected. | 
|  | */ | 
|  | deselectCell : function(cellIndex) { | 
|  | var cell = this.cells[cellIndex], | 
|  | cellDate = this.cellDates[cellIndex], | 
|  | cellDateIndex = this._indexOfSelectedFieldArray(cellDate); | 
|  |  | 
|  | var selectable = Dom.hasClass(cell, this.Style.CSS_CELL_SELECTABLE); | 
|  |  | 
|  | if (selectable) { | 
|  |  | 
|  | this.beforeDeselectEvent.fire(); | 
|  |  | 
|  | var selected = this.cfg.getProperty(DEF_CFG.SELECTED.key), | 
|  | dCellDate = this._toDate(cellDate), | 
|  | selectDate = cellDate.concat(); | 
|  |  | 
|  | if (cellDateIndex > -1) { | 
|  | if (this.cfg.getProperty(DEF_CFG.PAGEDATE.key).getMonth() == dCellDate.getMonth() && | 
|  | this.cfg.getProperty(DEF_CFG.PAGEDATE.key).getFullYear() == dCellDate.getFullYear()) { | 
|  | Dom.removeClass(cell, this.Style.CSS_CELL_SELECTED); | 
|  | } | 
|  | selected.splice(cellDateIndex, 1); | 
|  | } | 
|  |  | 
|  | if (this.parent) { | 
|  | this.parent.cfg.setProperty(DEF_CFG.SELECTED.key, selected); | 
|  | } else { | 
|  | this.cfg.setProperty(DEF_CFG.SELECTED.key, selected); | 
|  | } | 
|  |  | 
|  | this.deselectEvent.fire(selectDate); | 
|  | } | 
|  |  | 
|  | 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() { | 
|  | this.beforeDeselectEvent.fire(); | 
|  |  | 
|  | var cfgSelected = DEF_CFG.SELECTED.key, | 
|  | selected = this.cfg.getProperty(cfgSelected), | 
|  | count = selected.length, | 
|  | sel = selected.concat(); | 
|  |  | 
|  | if (this.parent) { | 
|  | this.parent.cfg.setProperty(cfgSelected, []); | 
|  | } else { | 
|  | this.cfg.setProperty(cfgSelected, []); | 
|  | } | 
|  |  | 
|  | if (count > 0) { | 
|  | this.deselectEvent.fire(sel); | 
|  | } | 
|  |  | 
|  | return this.getSelectedDates(); | 
|  | }, | 
|  |  | 
|  | // END SELECTION METHODS | 
|  |  | 
|  | // BEGIN TYPE CONVERSION METHODS | 
|  |  | 
|  | /** | 
|  | * Converts a date (either a JavaScript Date object, or a date string) to the internal data structure | 
|  | * used to represent dates: [[yyyy,mm,dd],[yyyy,mm,dd]]. | 
|  | * @method _toFieldArray | 
|  | * @private | 
|  | * @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 {Array[](Number[])}	Array of date field arrays | 
|  | */ | 
|  | _toFieldArray : function(date) { | 
|  | var returnDate = []; | 
|  |  | 
|  | if (date instanceof Date) { | 
|  | returnDate = [[date.getFullYear(), date.getMonth()+1, date.getDate()]]; | 
|  | } else if (Lang.isString(date)) { | 
|  | returnDate = this._parseDates(date); | 
|  | } else if (Lang.isArray(date)) { | 
|  | for (var i=0;i<date.length;++i) { | 
|  | var d = date[i]; | 
|  | returnDate[returnDate.length] = [d.getFullYear(),d.getMonth()+1,d.getDate()]; | 
|  | } | 
|  | } | 
|  |  | 
|  | return returnDate; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Converts a date field array [yyyy,mm,dd] to a JavaScript Date object. The date field array | 
|  | * is the format in which dates are as provided as arguments to selectEvent and deselectEvent listeners. | 
|  | * | 
|  | * @method toDate | 
|  | * @param	{Number[]}	dateFieldArray	The date field array to convert to a JavaScript Date. | 
|  | * @return	{Date}	JavaScript Date object representing the date field array. | 
|  | */ | 
|  | toDate : function(dateFieldArray) { | 
|  | return this._toDate(dateFieldArray); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Converts a date field array [yyyy,mm,dd] to a JavaScript Date object. | 
|  | * @method _toDate | 
|  | * @private | 
|  | * @deprecated Made public, toDate | 
|  | * @param	{Number[]}		dateFieldArray	The date field array to convert to a JavaScript Date. | 
|  | * @return	{Date}	JavaScript Date object representing the date field array | 
|  | */ | 
|  | _toDate : function(dateFieldArray) { | 
|  | if (dateFieldArray instanceof Date) { | 
|  | return dateFieldArray; | 
|  | } else { | 
|  | return DateMath.getDate(dateFieldArray[0],dateFieldArray[1]-1,dateFieldArray[2]); | 
|  | } | 
|  | }, | 
|  |  | 
|  | // END TYPE CONVERSION METHODS | 
|  |  | 
|  | // BEGIN UTILITY METHODS | 
|  |  | 
|  | /** | 
|  | * Converts a date field array [yyyy,mm,dd] to a JavaScript Date object. | 
|  | * @method _fieldArraysAreEqual | 
|  | * @private | 
|  | * @param	{Number[]}	array1	The first date field array to compare | 
|  | * @param	{Number[]}	array2	The first date field array to compare | 
|  | * @return	{Boolean}	The boolean that represents the equality of the two arrays | 
|  | */ | 
|  | _fieldArraysAreEqual : function(array1, array2) { | 
|  | var match = false; | 
|  |  | 
|  | if (array1[0]==array2[0]&&array1[1]==array2[1]&&array1[2]==array2[2]) { | 
|  | match=true; | 
|  | } | 
|  |  | 
|  | return match; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Gets the index of a date field array [yyyy,mm,dd] in the current list of selected dates. | 
|  | * @method	_indexOfSelectedFieldArray | 
|  | * @private | 
|  | * @param	{Number[]}		find	The date field array to search for | 
|  | * @return	{Number}			The index of the date field array within the collection of selected dates. | 
|  | *								-1 will be returned if the date is not found. | 
|  | */ | 
|  | _indexOfSelectedFieldArray : function(find) { | 
|  | var selected = -1, | 
|  | seldates = this.cfg.getProperty(DEF_CFG.SELECTED.key); | 
|  |  | 
|  | for (var s=0;s<seldates.length;++s) { | 
|  | var sArray = seldates[s]; | 
|  | if (find[0]==sArray[0]&&find[1]==sArray[1]&&find[2]==sArray[2]) { | 
|  | selected = s; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | return selected; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Determines whether a given date is OOM (out of month). | 
|  | * @method	isDateOOM | 
|  | * @param	{Date}	date	The JavaScript Date object for which to check the OOM status | 
|  | * @return	{Boolean}	true if the date is OOM | 
|  | */ | 
|  | isDateOOM : function(date) { | 
|  | return (date.getMonth() != this.cfg.getProperty(DEF_CFG.PAGEDATE.key).getMonth()); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Determines whether a given date is OOB (out of bounds - less than the mindate or more than the maxdate). | 
|  | * | 
|  | * @method	isDateOOB | 
|  | * @param	{Date}	date	The JavaScript Date object for which to check the OOB status | 
|  | * @return	{Boolean}	true if the date is OOB | 
|  | */ | 
|  | isDateOOB : function(date) { | 
|  | var minDate = this.cfg.getProperty(DEF_CFG.MINDATE.key), | 
|  | maxDate = this.cfg.getProperty(DEF_CFG.MAXDATE.key), | 
|  | dm = DateMath; | 
|  |  | 
|  | if (minDate) { | 
|  | minDate = dm.clearTime(minDate); | 
|  | } | 
|  | if (maxDate) { | 
|  | maxDate = dm.clearTime(maxDate); | 
|  | } | 
|  |  | 
|  | var clearedDate = new Date(date.getTime()); | 
|  | clearedDate = dm.clearTime(clearedDate); | 
|  |  | 
|  | return ((minDate && clearedDate.getTime() < minDate.getTime()) || (maxDate && clearedDate.getTime() > maxDate.getTime())); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Parses a pagedate configuration property value. The value can either be specified as a string of form "mm/yyyy" or a Date object | 
|  | * and is parsed into a Date object normalized to the first day of the month. If no value is passed in, the month and year from today's date are used to create the Date object | 
|  | * @method	_parsePageDate | 
|  | * @private | 
|  | * @param {Date|String}	date	Pagedate value which needs to be parsed | 
|  | * @return {Date}	The Date object representing the pagedate | 
|  | */ | 
|  | _parsePageDate : function(date) { | 
|  | var parsedDate; | 
|  |  | 
|  | if (date) { | 
|  | if (date instanceof Date) { | 
|  | parsedDate = DateMath.findMonthStart(date); | 
|  | } else { | 
|  | var month, year, aMonthYear; | 
|  | aMonthYear = date.split(this.cfg.getProperty(DEF_CFG.DATE_FIELD_DELIMITER.key)); | 
|  | month = parseInt(aMonthYear[this.cfg.getProperty(DEF_CFG.MY_MONTH_POSITION.key)-1], 10)-1; | 
|  | year = parseInt(aMonthYear[this.cfg.getProperty(DEF_CFG.MY_YEAR_POSITION.key)-1], 10); | 
|  |  | 
|  | parsedDate = DateMath.getDate(year, month, 1); | 
|  | } | 
|  | } else { | 
|  | parsedDate = DateMath.getDate(this.today.getFullYear(), this.today.getMonth(), 1); | 
|  | } | 
|  | return parsedDate; | 
|  | }, | 
|  |  | 
|  | // END UTILITY METHODS | 
|  |  | 
|  | // BEGIN EVENT HANDLERS | 
|  |  | 
|  | /** | 
|  | * Event executed before a date is selected in the calendar widget. | 
|  | * @deprecated Event handlers for this event should be susbcribed to beforeSelectEvent. | 
|  | */ | 
|  | onBeforeSelect : function() { | 
|  | if (this.cfg.getProperty(DEF_CFG.MULTI_SELECT.key) === false) { | 
|  | if (this.parent) { | 
|  | this.parent.callChildFunction("clearAllBodyCellStyles", this.Style.CSS_CELL_SELECTED); | 
|  | this.parent.deselectAll(); | 
|  | } else { | 
|  | this.clearAllBodyCellStyles(this.Style.CSS_CELL_SELECTED); | 
|  | this.deselectAll(); | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Event executed when a date is selected in the calendar widget. | 
|  | * @param	{Array}	selected	An array of date field arrays representing which date or dates were selected. Example: [ [2006,8,6],[2006,8,7],[2006,8,8] ] | 
|  | * @deprecated Event handlers for this event should be susbcribed to selectEvent. | 
|  | */ | 
|  | onSelect : function(selected) { }, | 
|  |  | 
|  | /** | 
|  | * Event executed before a date is deselected in the calendar widget. | 
|  | * @deprecated Event handlers for this event should be susbcribed to beforeDeselectEvent. | 
|  | */ | 
|  | onBeforeDeselect : function() { }, | 
|  |  | 
|  | /** | 
|  | * Event executed when a date is deselected in the calendar widget. | 
|  | * @param	{Array}	selected	An array of date field arrays representing which date or dates were deselected. Example: [ [2006,8,6],[2006,8,7],[2006,8,8] ] | 
|  | * @deprecated Event handlers for this event should be susbcribed to deselectEvent. | 
|  | */ | 
|  | onDeselect : function(deselected) { }, | 
|  |  | 
|  | /** | 
|  | * Event executed when the user navigates to a different calendar page. | 
|  | * @deprecated Event handlers for this event should be susbcribed to changePageEvent. | 
|  | */ | 
|  | onChangePage : function() { | 
|  | this.render(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Event executed when the calendar widget is rendered. | 
|  | * @deprecated Event handlers for this event should be susbcribed to renderEvent. | 
|  | */ | 
|  | onRender : function() { }, | 
|  |  | 
|  | /** | 
|  | * Event executed when the calendar widget is reset to its original state. | 
|  | * @deprecated Event handlers for this event should be susbcribed to resetEvemt. | 
|  | */ | 
|  | onReset : function() { this.render(); }, | 
|  |  | 
|  | /** | 
|  | * Event executed when the calendar widget is completely cleared to the current month with no selections. | 
|  | * @deprecated Event handlers for this event should be susbcribed to clearEvent. | 
|  | */ | 
|  | onClear : function() { this.render(); }, | 
|  |  | 
|  | /** | 
|  | * Validates the calendar widget. This method has no default implementation | 
|  | * and must be extended by subclassing the widget. | 
|  | * @return	Should return true if the widget validates, and false if | 
|  | * it doesn't. | 
|  | * @type Boolean | 
|  | */ | 
|  | validate : function() { return true; }, | 
|  |  | 
|  | // END EVENT HANDLERS | 
|  |  | 
|  | // BEGIN DATE PARSE METHODS | 
|  |  | 
|  | /** | 
|  | * Converts a date string to a date field array | 
|  | * @private | 
|  | * @param	{String}	sDate			Date string. Valid formats are mm/dd and mm/dd/yyyy. | 
|  | * @return				A date field array representing the string passed to the method | 
|  | * @type Array[](Number[]) | 
|  | */ | 
|  | _parseDate : function(sDate) { | 
|  | var aDate = sDate.split(this.Locale.DATE_FIELD_DELIMITER), | 
|  | rArray; | 
|  |  | 
|  | if (aDate.length == 2) { | 
|  | rArray = [aDate[this.Locale.MD_MONTH_POSITION-1],aDate[this.Locale.MD_DAY_POSITION-1]]; | 
|  | rArray.type = Calendar.MONTH_DAY; | 
|  | } else { | 
|  | rArray = [aDate[this.Locale.MDY_YEAR_POSITION-1],aDate[this.Locale.MDY_MONTH_POSITION-1],aDate[this.Locale.MDY_DAY_POSITION-1]]; | 
|  | rArray.type = Calendar.DATE; | 
|  | } | 
|  |  | 
|  | for (var i=0;i<rArray.length;i++) { | 
|  | rArray[i] = parseInt(rArray[i], 10); | 
|  | } | 
|  |  | 
|  | return rArray; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Converts a multi or single-date string to an array of date field arrays | 
|  | * @private | 
|  | * @param	{String}	sDates		Date string with one or more comma-delimited dates. Valid formats are mm/dd, mm/dd/yyyy, mm/dd/yyyy-mm/dd/yyyy | 
|  | * @return							An array of date field arrays | 
|  | * @type Array[](Number[]) | 
|  | */ | 
|  | _parseDates : function(sDates) { | 
|  | var aReturn = [], | 
|  | aDates = sDates.split(this.Locale.DATE_DELIMITER); | 
|  |  | 
|  | for (var d=0;d<aDates.length;++d) { | 
|  | var sDate = aDates[d]; | 
|  |  | 
|  | if (sDate.indexOf(this.Locale.DATE_RANGE_DELIMITER) != -1) { | 
|  | // This is a range | 
|  | var aRange = sDate.split(this.Locale.DATE_RANGE_DELIMITER), | 
|  | dateStart = this._parseDate(aRange[0]), | 
|  | dateEnd = this._parseDate(aRange[1]), | 
|  | fullRange = this._parseRange(dateStart, dateEnd); | 
|  |  | 
|  | aReturn = aReturn.concat(fullRange); | 
|  | } else { | 
|  | // This is not a range | 
|  | var aDate = this._parseDate(sDate); | 
|  | aReturn.push(aDate); | 
|  | } | 
|  | } | 
|  | return aReturn; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Converts a date range to the full list of included dates | 
|  | * @private | 
|  | * @param	{Number[]}	startDate	Date field array representing the first date in the range | 
|  | * @param	{Number[]}	endDate		Date field array representing the last date in the range | 
|  | * @return							An array of date field arrays | 
|  | * @type Array[](Number[]) | 
|  | */ | 
|  | _parseRange : function(startDate, endDate) { | 
|  | var dCurrent = DateMath.add(DateMath.getDate(startDate[0],startDate[1]-1,startDate[2]),DateMath.DAY,1), | 
|  | dEnd     = DateMath.getDate(endDate[0],  endDate[1]-1,  endDate[2]), | 
|  | results = []; | 
|  |  | 
|  | results.push(startDate); | 
|  | while (dCurrent.getTime() <= dEnd.getTime()) { | 
|  | results.push([dCurrent.getFullYear(),dCurrent.getMonth()+1,dCurrent.getDate()]); | 
|  | dCurrent = DateMath.add(dCurrent,DateMath.DAY,1); | 
|  | } | 
|  | return results; | 
|  | }, | 
|  |  | 
|  | // END DATE PARSE METHODS | 
|  |  | 
|  | // BEGIN RENDERER METHODS | 
|  |  | 
|  | /** | 
|  | * Resets the render stack of the current calendar to its original pre-render value. | 
|  | */ | 
|  | resetRenderers : function() { | 
|  | this.renderStack = this._renderStack.concat(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Removes all custom renderers added to the Calendar through the addRenderer, addMonthRenderer and | 
|  | * addWeekdayRenderer methods. Calendar's render method needs to be called after removing renderers | 
|  | * to re-render the Calendar without custom renderers applied. | 
|  | */ | 
|  | removeRenderers : function() { | 
|  | this._renderStack = []; | 
|  | this.renderStack = []; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Clears the inner HTML, CSS class and style information from the specified cell. | 
|  | * @method clearElement | 
|  | * @param	{HTMLTableCellElement} cell The cell to clear | 
|  | */ | 
|  | clearElement : function(cell) { | 
|  | cell.innerHTML = " "; | 
|  | cell.className=""; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * 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) { | 
|  | var aDates = this._parseDates(sDates); | 
|  | for (var i=0;i<aDates.length;++i) { | 
|  | var aDate = aDates[i]; | 
|  |  | 
|  | if (aDate.length == 2) { // this is either a range or a month/day combo | 
|  | if (aDate[0] instanceof Array) { // this is a range | 
|  | this._addRenderer(Calendar.RANGE,aDate,fnRender); | 
|  | } else { // this is a month/day combo | 
|  | this._addRenderer(Calendar.MONTH_DAY,aDate,fnRender); | 
|  | } | 
|  | } else if (aDate.length == 3) { | 
|  | this._addRenderer(Calendar.DATE,aDate,fnRender); | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * The private method used for adding cell renderers to the local render stack. | 
|  | * This method is called by other methods that set the renderer type prior to the method call. | 
|  | * @method _addRenderer | 
|  | * @private | 
|  | * @param	{String}	type		The type string that indicates the type of date renderer being added. | 
|  | *									Values are YAHOO.widget.Calendar.DATE, YAHOO.widget.Calendar.MONTH_DAY, YAHOO.widget.Calendar.WEEKDAY, | 
|  | *									YAHOO.widget.Calendar.RANGE, YAHOO.widget.Calendar.MONTH | 
|  | * @param	{Array}		aDates		An array of dates used to construct the renderer. The format varies based | 
|  | *									on the renderer type | 
|  | * @param	{Function}	fnRender	The function executed to render cells that match the render rules for this renderer. | 
|  | */ | 
|  | _addRenderer : function(type, aDates, fnRender) { | 
|  | var add = [type,aDates,fnRender]; | 
|  | this.renderStack.unshift(add); | 
|  | this._renderStack = this.renderStack.concat(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * 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) { | 
|  | this._addRenderer(Calendar.MONTH,[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 (Sunday = 1, Monday = 2 ... Saturday = 7) to associate with this renderer | 
|  | * @param	{Function}	fnRender	The function executed to render cells that match the render rules for this renderer. | 
|  | */ | 
|  | addWeekdayRenderer : function(weekday, fnRender) { | 
|  | this._addRenderer(Calendar.WEEKDAY,[weekday],fnRender); | 
|  | }, | 
|  |  | 
|  | // END RENDERER METHODS | 
|  |  | 
|  | // BEGIN CSS METHODS | 
|  |  | 
|  | /** | 
|  | * Removes all styles from all body cells in the current calendar table. | 
|  | * @method clearAllBodyCellStyles | 
|  | * @param	{style}	style The CSS class name to remove from all calendar body cells | 
|  | */ | 
|  | clearAllBodyCellStyles : function(style) { | 
|  | for (var c=0;c<this.cells.length;++c) { | 
|  | Dom.removeClass(this.cells[c],style); | 
|  | } | 
|  | }, | 
|  |  | 
|  | // END CSS METHODS | 
|  |  | 
|  | // BEGIN GETTER/SETTER METHODS | 
|  | /** | 
|  | * Sets the calendar's month explicitly | 
|  | * @method setMonth | 
|  | * @param {Number}	month		The numeric month, from 0 (January) to 11 (December) | 
|  | */ | 
|  | setMonth : function(month) { | 
|  | var cfgPageDate = DEF_CFG.PAGEDATE.key, | 
|  | current = this.cfg.getProperty(cfgPageDate); | 
|  | current.setMonth(parseInt(month, 10)); | 
|  | this.cfg.setProperty(cfgPageDate, current); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Sets the calendar's year explicitly. | 
|  | * @method setYear | 
|  | * @param {Number}	year		The numeric 4-digit year | 
|  | */ | 
|  | setYear : function(year) { | 
|  | var cfgPageDate = DEF_CFG.PAGEDATE.key, | 
|  | current = this.cfg.getProperty(cfgPageDate); | 
|  |  | 
|  | current.setFullYear(parseInt(year, 10)); | 
|  | this.cfg.setProperty(cfgPageDate, current); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Gets the list of currently selected dates from the calendar. | 
|  | * @method getSelectedDates | 
|  | * @return {Date[]} An array of currently selected JavaScript Date objects. | 
|  | */ | 
|  | getSelectedDates : function() { | 
|  | var returnDates = [], | 
|  | 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; | 
|  | }, | 
|  |  | 
|  | /// END GETTER/SETTER METHODS /// | 
|  |  | 
|  | /** | 
|  | * Hides the Calendar's outer container from view. | 
|  | * @method hide | 
|  | */ | 
|  | hide : function() { | 
|  | if (this.beforeHideEvent.fire()) { | 
|  | this.oDomContainer.style.display = "none"; | 
|  | this.hideEvent.fire(); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Shows the Calendar's outer container. | 
|  | * @method show | 
|  | */ | 
|  | show : function() { | 
|  | if (this.beforeShowEvent.fire()) { | 
|  | this.oDomContainer.style.display = "block"; | 
|  | this.showEvent.fire(); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Returns a string representing the current browser. | 
|  | * @deprecated As of 2.3.0, environment information is available in YAHOO.env.ua | 
|  | * @see YAHOO.env.ua | 
|  | * @property browser | 
|  | * @type String | 
|  | */ | 
|  | browser : (function() { | 
|  | var ua = navigator.userAgent.toLowerCase(); | 
|  | if (ua.indexOf('opera')!=-1) { // Opera (check first in case of spoof) | 
|  | return 'opera'; | 
|  | } else if (ua.indexOf('msie 7')!=-1) { // IE7 | 
|  | return 'ie7'; | 
|  | } else if (ua.indexOf('msie') !=-1) { // IE | 
|  | return 'ie'; | 
|  | } else if (ua.indexOf('safari')!=-1) { // Safari (check before Gecko because it includes "like Gecko") | 
|  | return 'safari'; | 
|  | } else if (ua.indexOf('gecko') != -1) { // Gecko | 
|  | return 'gecko'; | 
|  | } else { | 
|  | return false; | 
|  | } | 
|  | })(), | 
|  | /** | 
|  | * Returns a string representation of the object. | 
|  | * @method toString | 
|  | * @return {String}	A string representation of the Calendar object. | 
|  | */ | 
|  | toString : function() { | 
|  | return "Calendar " + this.id; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Destroys the Calendar instance. The method will remove references | 
|  | * to HTML elements, remove any event listeners added by the Calendar, | 
|  | * and destroy the Config and CalendarNavigator instances it has created. | 
|  | * | 
|  | * @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, "withtitle"); | 
|  | Dom.removeClass(cal.oDomContainer, cal.Style.CSS_CONTAINER); | 
|  | Dom.removeClass(cal.oDomContainer, cal.Style.CSS_SINGLE); | 
|  | cal.oDomContainer.innerHTML = ""; | 
|  |  | 
|  | // JS-to-DOM references | 
|  | cal.oDomContainer = null; | 
|  | cal.cells = null; | 
|  |  | 
|  | this.destroyEvent.fire(); | 
|  | } | 
|  | } | 
|  | }; | 
|  |  | 
|  | YAHOO.widget.Calendar = Calendar; | 
|  |  | 
|  | /** | 
|  | * @namespace YAHOO.widget | 
|  | * @class Calendar_Core | 
|  | * @extends YAHOO.widget.Calendar | 
|  | * @deprecated The old Calendar_Core class is no longer necessary. | 
|  | */ | 
|  | YAHOO.widget.Calendar_Core = YAHOO.widget.Calendar; | 
|  |  | 
|  | YAHOO.widget.Cal_Core = YAHOO.widget.Calendar; | 
|  |  | 
|  | })(); | 
|  |  | 
|  | (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.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.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); | 
|  | } | 
|  |  | 
|  | }, | 
|  |  | 
|  | 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 selection is made | 
|  | * @event beforeSelectEvent | 
|  | */ | 
|  | me.beforeSelectEvent = new CE(defEvents.BEFORE_SELECT); | 
|  | me.beforeSelectEvent.subscribe = sub; me.beforeSelectEvent.unsubscribe = unsub; | 
|  |  | 
|  | /** | 
|  | * Fired when a 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 selection is made | 
|  | * @event beforeDeselectEvent | 
|  | */ | 
|  | me.beforeDeselectEvent = new CE(defEvents.BEFORE_DESELECT); | 
|  | me.beforeDeselectEvent.subscribe = sub; me.beforeDeselectEvent.unsubscribe = unsub; | 
|  |  | 
|  | /** | 
|  | * Fired when a selection is made | 
|  | * @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 = "_", | 
|  | 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; | 
|  |  | 
|  | var cal = this.constructChild(calId, calContainerId, childConfig); | 
|  | var caldate = cal.cfg.getProperty(cfgPageDate); | 
|  | this._setMonthOnDate(caldate, caldate.getMonth() + p); | 
|  | cal.cfg.setProperty(cfgPageDate, caldate); | 
|  |  | 
|  | Dom.removeClass(cal.oDomContainer, this.Style.CSS_SINGLE); | 
|  | Dom.addClass(cal.oDomContainer, groupCalClass); | 
|  |  | 
|  | if (p===0) { | 
|  | 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; | 
|  |  | 
|  | })(); | 
|  |  | 
|  | /** | 
|  | * The CalendarNavigator is used along with a Calendar/CalendarGroup to | 
|  | * provide a Month/Year popup navigation control, allowing the user to navigate | 
|  | * to a specific month/year in the Calendar/CalendarGroup without having to | 
|  | * scroll through months sequentially | 
|  | * | 
|  | * @namespace YAHOO.widget | 
|  | * @class CalendarNavigator | 
|  | * @constructor | 
|  | * @param {Calendar|CalendarGroup} cal The instance of the Calendar or CalendarGroup to which this CalendarNavigator should be attached. | 
|  | */ | 
|  | YAHOO.widget.CalendarNavigator = function(cal) { | 
|  | this.init(cal); | 
|  | }; | 
|  |  | 
|  | (function() { | 
|  | // Setup static properties (inside anon fn, so that we can use shortcuts) | 
|  | var CN = YAHOO.widget.CalendarNavigator; | 
|  |  | 
|  | /** | 
|  | * YAHOO.widget.CalendarNavigator.CLASSES contains constants | 
|  | * for the class values applied to the CalendarNaviatgator's | 
|  | * DOM elements | 
|  | * @property YAHOO.widget.CalendarNavigator.CLASSES | 
|  | * @type Object | 
|  | * @static | 
|  | */ | 
|  | CN.CLASSES = { | 
|  | /** | 
|  | * Class applied to the Calendar Navigator's bounding box | 
|  | * @property YAHOO.widget.CalendarNavigator.CLASSES.NAV | 
|  | * @type String | 
|  | * @static | 
|  | */ | 
|  | NAV :"yui-cal-nav", | 
|  | /** | 
|  | * Class applied to the Calendar/CalendarGroup's bounding box to indicate | 
|  | * the Navigator is currently visible | 
|  | * @property YAHOO.widget.CalendarNavigator.CLASSES.NAV_VISIBLE | 
|  | * @type String | 
|  | * @static | 
|  | */ | 
|  | NAV_VISIBLE: "yui-cal-nav-visible", | 
|  | /** | 
|  | * Class applied to the Navigator mask's bounding box | 
|  | * @property YAHOO.widget.CalendarNavigator.CLASSES.MASK | 
|  | * @type String | 
|  | * @static | 
|  | */ | 
|  | MASK : "yui-cal-nav-mask", | 
|  | /** | 
|  | * Class applied to the year label/control bounding box | 
|  | * @property YAHOO.widget.CalendarNavigator.CLASSES.YEAR | 
|  | * @type String | 
|  | * @static | 
|  | */ | 
|  | YEAR : "yui-cal-nav-y", | 
|  | /** | 
|  | * Class applied to the month label/control bounding box | 
|  | * @property YAHOO.widget.CalendarNavigator.CLASSES.MONTH | 
|  | * @type String | 
|  | * @static | 
|  | */ | 
|  | MONTH : "yui-cal-nav-m", | 
|  | /** | 
|  | * Class applied to the submit/cancel button's bounding box | 
|  | * @property YAHOO.widget.CalendarNavigator.CLASSES.BUTTONS | 
|  | * @type String | 
|  | * @static | 
|  | */ | 
|  | BUTTONS : "yui-cal-nav-b", | 
|  | /** | 
|  | * Class applied to buttons wrapping element | 
|  | * @property YAHOO.widget.CalendarNavigator.CLASSES.BUTTON | 
|  | * @type String | 
|  | * @static | 
|  | */ | 
|  | BUTTON : "yui-cal-nav-btn", | 
|  | /** | 
|  | * Class applied to the validation error area's bounding box | 
|  | * @property YAHOO.widget.CalendarNavigator.CLASSES.ERROR | 
|  | * @type String | 
|  | * @static | 
|  | */ | 
|  | ERROR : "yui-cal-nav-e", | 
|  | /** | 
|  | * Class applied to the year input control | 
|  | * @property YAHOO.widget.CalendarNavigator.CLASSES.YEAR_CTRL | 
|  | * @type String | 
|  | * @static | 
|  | */ | 
|  | YEAR_CTRL : "yui-cal-nav-yc", | 
|  | /** | 
|  | * Class applied to the month input control | 
|  | * @property YAHOO.widget.CalendarNavigator.CLASSES.MONTH_CTRL | 
|  | * @type String | 
|  | * @static | 
|  | */ | 
|  | MONTH_CTRL : "yui-cal-nav-mc", | 
|  | /** | 
|  | * Class applied to controls with invalid data (e.g. a year input field with invalid an year) | 
|  | * @property YAHOO.widget.CalendarNavigator.CLASSES.INVALID | 
|  | * @type String | 
|  | * @static | 
|  | */ | 
|  | INVALID : "yui-invalid", | 
|  | /** | 
|  | * Class applied to default controls | 
|  | * @property YAHOO.widget.CalendarNavigator.CLASSES.DEFAULT | 
|  | * @type String | 
|  | * @static | 
|  | */ | 
|  | DEFAULT : "yui-default" | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * Object literal containing the default configuration values for the CalendarNavigator | 
|  | * The configuration object is expected to follow the format below, with the properties being | 
|  | * case sensitive. | 
|  | * <dl> | 
|  | * <dt>strings</dt> | 
|  | * <dd><em>Object</em> :  An object with the properties shown below, defining the string labels to use in the Navigator's UI | 
|  | *     <dl> | 
|  | *         <dt>month</dt><dd><em>String</em> : The string to use for the month label. Defaults to "Month".</dd> | 
|  | *         <dt>year</dt><dd><em>String</em> : The string to use for the year label. Defaults to "Year".</dd> | 
|  | *         <dt>submit</dt><dd><em>String</em> : The string to use for the submit button label. Defaults to "Okay".</dd> | 
|  | *         <dt>cancel</dt><dd><em>String</em> : The string to use for the cancel button label. Defaults to "Cancel".</dd> | 
|  | *         <dt>invalidYear</dt><dd><em>String</em> : The string to use for invalid year values. Defaults to "Year needs to be a number".</dd> | 
|  | *     </dl> | 
|  | * </dd> | 
|  | * <dt>monthFormat</dt><dd><em>String</em> : The month format to use. Either YAHOO.widget.Calendar.LONG, or YAHOO.widget.Calendar.SHORT. Defaults to YAHOO.widget.Calendar.LONG</dd> | 
|  | * <dt>initialFocus</dt><dd><em>String</em> : Either "year" or "month" specifying which input control should get initial focus. Defaults to "year"</dd> | 
|  | * </dl> | 
|  | * @property _DEFAULT_CFG | 
|  | * @protected | 
|  | * @type Object | 
|  | * @static | 
|  | */ | 
|  | CN._DEFAULT_CFG = { | 
|  | strings : { | 
|  | month: "Month", | 
|  | year: "Year", | 
|  | submit: "Okay", | 
|  | cancel: "Cancel", | 
|  | invalidYear : "Year needs to be a number" | 
|  | }, | 
|  | monthFormat: YAHOO.widget.Calendar.LONG, | 
|  | initialFocus: "year" | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * The suffix added to the Calendar/CalendarGroup's ID, to generate | 
|  | * a unique ID for the Navigator and it's bounding box. | 
|  | * @property YAHOO.widget.CalendarNavigator.ID_SUFFIX | 
|  | * @static | 
|  | * @type String | 
|  | * @final | 
|  | */ | 
|  | CN.ID_SUFFIX = "_nav"; | 
|  | /** | 
|  | * The suffix added to the Navigator's ID, to generate | 
|  | * a unique ID for the month control. | 
|  | * @property YAHOO.widget.CalendarNavigator.MONTH_SUFFIX | 
|  | * @static | 
|  | * @type String | 
|  | * @final | 
|  | */ | 
|  | CN.MONTH_SUFFIX = "_month"; | 
|  | /** | 
|  | * The suffix added to the Navigator's ID, to generate | 
|  | * a unique ID for the year control. | 
|  | * @property YAHOO.widget.CalendarNavigator.YEAR_SUFFIX | 
|  | * @static | 
|  | * @type String | 
|  | * @final | 
|  | */ | 
|  | CN.YEAR_SUFFIX = "_year"; | 
|  | /** | 
|  | * The suffix added to the Navigator's ID, to generate | 
|  | * a unique ID for the error bounding box. | 
|  | * @property YAHOO.widget.CalendarNavigator.ERROR_SUFFIX | 
|  | * @static | 
|  | * @type String | 
|  | * @final | 
|  | */ | 
|  | CN.ERROR_SUFFIX = "_error"; | 
|  | /** | 
|  | * The suffix added to the Navigator's ID, to generate | 
|  | * a unique ID for the "Cancel" button. | 
|  | * @property YAHOO.widget.CalendarNavigator.CANCEL_SUFFIX | 
|  | * @static | 
|  | * @type String | 
|  | * @final | 
|  | */ | 
|  | CN.CANCEL_SUFFIX = "_cancel"; | 
|  | /** | 
|  | * The suffix added to the Navigator's ID, to generate | 
|  | * a unique ID for the "Submit" button. | 
|  | * @property YAHOO.widget.CalendarNavigator.SUBMIT_SUFFIX | 
|  | * @static | 
|  | * @type String | 
|  | * @final | 
|  | */ | 
|  | CN.SUBMIT_SUFFIX = "_submit"; | 
|  |  | 
|  | /** | 
|  | * The number of digits to which the year input control is to be limited. | 
|  | * @property YAHOO.widget.CalendarNavigator.YR_MAX_DIGITS | 
|  | * @static | 
|  | * @type Number | 
|  | */ | 
|  | CN.YR_MAX_DIGITS = 4; | 
|  |  | 
|  | /** | 
|  | * The amount by which to increment the current year value, | 
|  | * when the arrow up/down key is pressed on the year control | 
|  | * @property YAHOO.widget.CalendarNavigator.YR_MINOR_INC | 
|  | * @static | 
|  | * @type Number | 
|  | */ | 
|  | CN.YR_MINOR_INC = 1; | 
|  |  | 
|  | /** | 
|  | * The amount by which to increment the current year value, | 
|  | * when the page up/down key is pressed on the year control | 
|  | * @property YAHOO.widget.CalendarNavigator.YR_MAJOR_INC | 
|  | * @static | 
|  | * @type Number | 
|  | */ | 
|  | CN.YR_MAJOR_INC = 10; | 
|  |  | 
|  | /** | 
|  | * Artificial delay (in ms) between the time the Navigator is hidden | 
|  | * and the Calendar/CalendarGroup state is updated. Allows the user | 
|  | * the see the Calendar/CalendarGroup page changing. If set to 0 | 
|  | * the Calendar/CalendarGroup page will be updated instantly | 
|  | * @property YAHOO.widget.CalendarNavigator.UPDATE_DELAY | 
|  | * @static | 
|  | * @type Number | 
|  | */ | 
|  | CN.UPDATE_DELAY = 50; | 
|  |  | 
|  | /** | 
|  | * Regular expression used to validate the year input | 
|  | * @property YAHOO.widget.CalendarNavigator.YR_PATTERN | 
|  | * @static | 
|  | * @type RegExp | 
|  | */ | 
|  | CN.YR_PATTERN = /^\d+$/; | 
|  | /** | 
|  | * Regular expression used to trim strings | 
|  | * @property YAHOO.widget.CalendarNavigator.TRIM | 
|  | * @static | 
|  | * @type RegExp | 
|  | */ | 
|  | CN.TRIM = /^\s*(.*?)\s*$/; | 
|  | })(); | 
|  |  | 
|  | YAHOO.widget.CalendarNavigator.prototype = { | 
|  |  | 
|  | /** | 
|  | * The unique ID for this CalendarNavigator instance | 
|  | * @property id | 
|  | * @type String | 
|  | */ | 
|  | id : null, | 
|  |  | 
|  | /** | 
|  | * The Calendar/CalendarGroup instance to which the navigator belongs | 
|  | * @property cal | 
|  | * @type {Calendar|CalendarGroup} | 
|  | */ | 
|  | cal : null, | 
|  |  | 
|  | /** | 
|  | * Reference to the HTMLElement used to render the navigator's bounding box | 
|  | * @property navEl | 
|  | * @type HTMLElement | 
|  | */ | 
|  | navEl : null, | 
|  |  | 
|  | /** | 
|  | * Reference to the HTMLElement used to render the navigator's mask | 
|  | * @property maskEl | 
|  | * @type HTMLElement | 
|  | */ | 
|  | maskEl : null, | 
|  |  | 
|  | /** | 
|  | * Reference to the HTMLElement used to input the year | 
|  | * @property yearEl | 
|  | * @type HTMLElement | 
|  | */ | 
|  | yearEl : null, | 
|  |  | 
|  | /** | 
|  | * Reference to the HTMLElement used to input the month | 
|  | * @property monthEl | 
|  | * @type HTMLElement | 
|  | */ | 
|  | monthEl : null, | 
|  |  | 
|  | /** | 
|  | * Reference to the HTMLElement used to display validation errors | 
|  | * @property errorEl | 
|  | * @type HTMLElement | 
|  | */ | 
|  | errorEl : null, | 
|  |  | 
|  | /** | 
|  | * Reference to the HTMLElement used to update the Calendar/Calendar group | 
|  | * with the month/year values | 
|  | * @property submitEl | 
|  | * @type HTMLElement | 
|  | */ | 
|  | submitEl : null, | 
|  |  | 
|  | /** | 
|  | * Reference to the HTMLElement used to hide the navigator without updating the | 
|  | * Calendar/Calendar group | 
|  | * @property cancelEl | 
|  | * @type HTMLElement | 
|  | */ | 
|  | cancelEl : null, | 
|  |  | 
|  | /** | 
|  | * Reference to the first focusable control in the navigator (by default monthEl) | 
|  | * @property firstCtrl | 
|  | * @type HTMLElement | 
|  | */ | 
|  | firstCtrl : null, | 
|  |  | 
|  | /** | 
|  | * Reference to the last focusable control in the navigator (by default cancelEl) | 
|  | * @property lastCtrl | 
|  | * @type HTMLElement | 
|  | */ | 
|  | lastCtrl : null, | 
|  |  | 
|  | /** | 
|  | * The document containing the Calendar/Calendar group instance | 
|  | * @protected | 
|  | * @property _doc | 
|  | * @type HTMLDocument | 
|  | */ | 
|  | _doc : null, | 
|  |  | 
|  | /** | 
|  | * Internal state property for the current year displayed in the navigator | 
|  | * @protected | 
|  | * @property _year | 
|  | * @type Number | 
|  | */ | 
|  | _year: null, | 
|  |  | 
|  | /** | 
|  | * Internal state property for the current month index displayed in the navigator | 
|  | * @protected | 
|  | * @property _month | 
|  | * @type Number | 
|  | */ | 
|  | _month: 0, | 
|  |  | 
|  | /** | 
|  | * Private internal state property which indicates whether or not the | 
|  | * Navigator has been rendered. | 
|  | * @private | 
|  | * @property __rendered | 
|  | * @type Boolean | 
|  | */ | 
|  | __rendered: false, | 
|  |  | 
|  | /** | 
|  | * Init lifecycle method called as part of construction | 
|  | * | 
|  | * @method init | 
|  | * @param {Calendar} cal The instance of the Calendar or CalendarGroup to which this CalendarNavigator should be attached | 
|  | */ | 
|  | init : function(cal) { | 
|  | var calBox = cal.oDomContainer; | 
|  |  | 
|  | this.cal = cal; | 
|  | this.id = calBox.id + YAHOO.widget.CalendarNavigator.ID_SUFFIX; | 
|  | this._doc = calBox.ownerDocument; | 
|  |  | 
|  | /** | 
|  | * Private flag, to identify IE6/IE7 Quirks | 
|  | * @private | 
|  | * @property __isIEQuirks | 
|  | */ | 
|  | var ie = YAHOO.env.ua.ie; | 
|  | this.__isIEQuirks = (ie && ((ie <= 6) || (ie === 7 && this._doc.compatMode == "BackCompat"))); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Displays the navigator and mask, updating the input controls to reflect the | 
|  | * currently set month and year. The show method will invoke the render method | 
|  | * if the navigator has not been renderered already, allowing for lazy rendering | 
|  | * of the control. | 
|  | * | 
|  | * The show method will fire the Calendar/CalendarGroup's beforeShowNav and showNav events | 
|  | * | 
|  | * @method show | 
|  | */ | 
|  | show : function() { | 
|  | var CLASSES = YAHOO.widget.CalendarNavigator.CLASSES; | 
|  |  | 
|  | if (this.cal.beforeShowNavEvent.fire()) { | 
|  | if (!this.__rendered) { | 
|  | this.render(); | 
|  | } | 
|  | this.clearErrors(); | 
|  |  | 
|  | this._updateMonthUI(); | 
|  | this._updateYearUI(); | 
|  | this._show(this.navEl, true); | 
|  |  | 
|  | this.setInitialFocus(); | 
|  | this.showMask(); | 
|  |  | 
|  | YAHOO.util.Dom.addClass(this.cal.oDomContainer, CLASSES.NAV_VISIBLE); | 
|  | this.cal.showNavEvent.fire(); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Hides the navigator and mask | 
|  | * | 
|  | * The show method will fire the Calendar/CalendarGroup's beforeHideNav event and hideNav events | 
|  | * @method hide | 
|  | */ | 
|  | hide : function() { | 
|  | var CLASSES = YAHOO.widget.CalendarNavigator.CLASSES; | 
|  |  | 
|  | if (this.cal.beforeHideNavEvent.fire()) { | 
|  | this._show(this.navEl, false); | 
|  | this.hideMask(); | 
|  | YAHOO.util.Dom.removeClass(this.cal.oDomContainer, CLASSES.NAV_VISIBLE); | 
|  | this.cal.hideNavEvent.fire(); | 
|  | } | 
|  | }, | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Displays the navigator's mask element | 
|  | * | 
|  | * @method showMask | 
|  | */ | 
|  | showMask : function() { | 
|  | this._show(this.maskEl, true); | 
|  | if (this.__isIEQuirks) { | 
|  | this._syncMask(); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Hides the navigator's mask element | 
|  | * | 
|  | * @method hideMask | 
|  | */ | 
|  | hideMask : function() { | 
|  | this._show(this.maskEl, false); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Returns the current month set on the navigator | 
|  | * | 
|  | * Note: This may not be the month set in the UI, if | 
|  | * the UI contains an invalid value. | 
|  | * | 
|  | * @method getMonth | 
|  | * @return {Number} The Navigator's current month index | 
|  | */ | 
|  | getMonth: function() { | 
|  | return this._month; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Returns the current year set on the navigator | 
|  | * | 
|  | * Note: This may not be the year set in the UI, if | 
|  | * the UI contains an invalid value. | 
|  | * | 
|  | * @method getYear | 
|  | * @return {Number} The Navigator's current year value | 
|  | */ | 
|  | getYear: function() { | 
|  | return this._year; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Sets the current month on the Navigator, and updates the UI | 
|  | * | 
|  | * @method setMonth | 
|  | * @param {Number} nMonth The month index, from 0 (Jan) through 11 (Dec). | 
|  | */ | 
|  | setMonth : function(nMonth) { | 
|  | if (nMonth >= 0 && nMonth < 12) { | 
|  | this._month = nMonth; | 
|  | } | 
|  | this._updateMonthUI(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Sets the current year on the Navigator, and updates the UI. If the | 
|  | * provided year is invalid, it will not be set. | 
|  | * | 
|  | * @method setYear | 
|  | * @param {Number} nYear The full year value to set the Navigator to. | 
|  | */ | 
|  | setYear : function(nYear) { | 
|  | var yrPattern = YAHOO.widget.CalendarNavigator.YR_PATTERN; | 
|  | if (YAHOO.lang.isNumber(nYear) && yrPattern.test(nYear+"")) { | 
|  | this._year = nYear; | 
|  | } | 
|  | this._updateYearUI(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders the HTML for the navigator, adding it to the | 
|  | * document and attaches event listeners if it has not | 
|  | * already been rendered. | 
|  | * | 
|  | * @method render | 
|  | */ | 
|  | render: function() { | 
|  | this.cal.beforeRenderNavEvent.fire(); | 
|  | if (!this.__rendered) { | 
|  | this.createNav(); | 
|  | this.createMask(); | 
|  | this.applyListeners(); | 
|  | this.__rendered = true; | 
|  | } | 
|  | this.cal.renderNavEvent.fire(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Creates the navigator's containing HTMLElement, it's contents, and appends | 
|  | * the containg element to the Calendar/CalendarGroup's container. | 
|  | * | 
|  | * @method createNav | 
|  | */ | 
|  | createNav : function() { | 
|  | var NAV = YAHOO.widget.CalendarNavigator; | 
|  | var doc = this._doc; | 
|  |  | 
|  | var d = doc.createElement("div"); | 
|  | d.className = NAV.CLASSES.NAV; | 
|  |  | 
|  | var htmlBuf = this.renderNavContents([]); | 
|  |  | 
|  | d.innerHTML = htmlBuf.join(''); | 
|  | this.cal.oDomContainer.appendChild(d); | 
|  |  | 
|  | this.navEl = d; | 
|  |  | 
|  | this.yearEl = doc.getElementById(this.id + NAV.YEAR_SUFFIX); | 
|  | this.monthEl = doc.getElementById(this.id + NAV.MONTH_SUFFIX); | 
|  | this.errorEl = doc.getElementById(this.id + NAV.ERROR_SUFFIX); | 
|  | this.submitEl = doc.getElementById(this.id + NAV.SUBMIT_SUFFIX); | 
|  | this.cancelEl = doc.getElementById(this.id + NAV.CANCEL_SUFFIX); | 
|  |  | 
|  | if (YAHOO.env.ua.gecko && this.yearEl && this.yearEl.type == "text") { | 
|  | // Avoid XUL error on focus, select [ https://bugzilla.mozilla.org/show_bug.cgi?id=236791, | 
|  | // supposedly fixed in 1.8.1, but there are reports of it still being around for methods other than blur ] | 
|  | this.yearEl.setAttribute("autocomplete", "off"); | 
|  | } | 
|  |  | 
|  | this._setFirstLastElements(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Creates the Mask HTMLElement and appends it to the Calendar/CalendarGroups | 
|  | * container. | 
|  | * | 
|  | * @method createMask | 
|  | */ | 
|  | createMask : function() { | 
|  | var C = YAHOO.widget.CalendarNavigator.CLASSES; | 
|  |  | 
|  | var d = this._doc.createElement("div"); | 
|  | d.className = C.MASK; | 
|  |  | 
|  | this.cal.oDomContainer.appendChild(d); | 
|  | this.maskEl = d; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Used to set the width/height of the mask in pixels to match the Calendar Container. | 
|  | * Currently only used for IE6 and IE7 quirks mode. The other A-Grade browser are handled using CSS (width/height 100%). | 
|  | * <p> | 
|  | * The method is also registered as an HTMLElement resize listener on the Calendars container element. | 
|  | * </p> | 
|  | * @protected | 
|  | * @method _syncMask | 
|  | */ | 
|  | _syncMask : function() { | 
|  | var c = this.cal.oDomContainer; | 
|  | if (c && this.maskEl) { | 
|  | var r = YAHOO.util.Dom.getRegion(c); | 
|  | YAHOO.util.Dom.setStyle(this.maskEl, "width", r.right - r.left + "px"); | 
|  | YAHOO.util.Dom.setStyle(this.maskEl, "height", r.bottom - r.top + "px"); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders the contents of the navigator | 
|  | * | 
|  | * @method renderNavContents | 
|  | * | 
|  | * @param {Array} html The HTML buffer to append the HTML to. | 
|  | * @return {Array} A reference to the buffer passed in. | 
|  | */ | 
|  | renderNavContents : function(html) { | 
|  | var NAV = YAHOO.widget.CalendarNavigator, | 
|  | C = NAV.CLASSES, | 
|  | h = html; // just to use a shorter name | 
|  |  | 
|  | h[h.length] = '<div class="' + C.MONTH + '">'; | 
|  | this.renderMonth(h); | 
|  | h[h.length] = '</div>'; | 
|  | h[h.length] = '<div class="' + C.YEAR + '">'; | 
|  | this.renderYear(h); | 
|  | h[h.length] = '</div>'; | 
|  | h[h.length] = '<div class="' + C.BUTTONS + '">'; | 
|  | this.renderButtons(h); | 
|  | h[h.length] = '</div>'; | 
|  | h[h.length] = '<div class="' + C.ERROR + '" id="' + this.id + NAV.ERROR_SUFFIX + '"></div>'; | 
|  |  | 
|  | return h; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders the month label and control for the navigator | 
|  | * | 
|  | * @method renderNavContents | 
|  | * @param {Array} html The HTML buffer to append the HTML to. | 
|  | * @return {Array} A reference to the buffer passed in. | 
|  | */ | 
|  | renderMonth : function(html) { | 
|  | var NAV = YAHOO.widget.CalendarNavigator, | 
|  | C = NAV.CLASSES; | 
|  |  | 
|  | var id = this.id + NAV.MONTH_SUFFIX, | 
|  | mf = this.__getCfg("monthFormat"), | 
|  | months = this.cal.cfg.getProperty((mf == YAHOO.widget.Calendar.SHORT) ? "MONTHS_SHORT" : "MONTHS_LONG"), | 
|  | h = html; | 
|  |  | 
|  | if (months && months.length > 0) { | 
|  | h[h.length] = '<label for="' + id + '">'; | 
|  | h[h.length] = this.__getCfg("month", true); | 
|  | h[h.length] = '</label>'; | 
|  | h[h.length] = '<select name="' + id + '" id="' + id + '" class="' + C.MONTH_CTRL + '">'; | 
|  | for (var i = 0; i < months.length; i++) { | 
|  | h[h.length] = '<option value="' + i + '">'; | 
|  | h[h.length] = months[i]; | 
|  | h[h.length] = '</option>'; | 
|  | } | 
|  | h[h.length] = '</select>'; | 
|  | } | 
|  | return h; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders the year label and control for the navigator | 
|  | * | 
|  | * @method renderYear | 
|  | * @param {Array} html The HTML buffer to append the HTML to. | 
|  | * @return {Array} A reference to the buffer passed in. | 
|  | */ | 
|  | renderYear : function(html) { | 
|  | var NAV = YAHOO.widget.CalendarNavigator, | 
|  | C = NAV.CLASSES; | 
|  |  | 
|  | var id = this.id + NAV.YEAR_SUFFIX, | 
|  | size = NAV.YR_MAX_DIGITS, | 
|  | h = html; | 
|  |  | 
|  | h[h.length] = '<label for="' + id + '">'; | 
|  | h[h.length] = this.__getCfg("year", true); | 
|  | h[h.length] = '</label>'; | 
|  | h[h.length] = '<input type="text" name="' + id + '" id="' + id + '" class="' + C.YEAR_CTRL + '" maxlength="' + size + '"/>'; | 
|  | return h; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Renders the submit/cancel buttons for the navigator | 
|  | * | 
|  | * @method renderButton | 
|  | * @return {String} The HTML created for the Button UI | 
|  | */ | 
|  | renderButtons : function(html) { | 
|  | var C = YAHOO.widget.CalendarNavigator.CLASSES; | 
|  | var h = html; | 
|  |  | 
|  | h[h.length] = '<span class="' + C.BUTTON + ' ' + C.DEFAULT + '">'; | 
|  | h[h.length] = '<button type="button" id="' + this.id + '_submit' + '">'; | 
|  | h[h.length] = this.__getCfg("submit", true); | 
|  | h[h.length] = '</button>'; | 
|  | h[h.length] = '</span>'; | 
|  | h[h.length] = '<span class="' + C.BUTTON +'">'; | 
|  | h[h.length] = '<button type="button" id="' + this.id + '_cancel' + '">'; | 
|  | h[h.length] = this.__getCfg("cancel", true); | 
|  | h[h.length] = '</button>'; | 
|  | h[h.length] = '</span>'; | 
|  |  | 
|  | return h; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Attaches DOM event listeners to the rendered elements | 
|  | * <p> | 
|  | * The method will call applyKeyListeners, to setup keyboard specific | 
|  | * listeners | 
|  | * </p> | 
|  | * @method applyListeners | 
|  | */ | 
|  | applyListeners : function() { | 
|  | var E = YAHOO.util.Event; | 
|  |  | 
|  | function yearUpdateHandler() { | 
|  | if (this.validate()) { | 
|  | this.setYear(this._getYearFromUI()); | 
|  | } | 
|  | } | 
|  |  | 
|  | function monthUpdateHandler() { | 
|  | this.setMonth(this._getMonthFromUI()); | 
|  | } | 
|  |  | 
|  | E.on(this.submitEl, "click", this.submit, this, true); | 
|  | E.on(this.cancelEl, "click", this.cancel, this, true); | 
|  | E.on(this.yearEl, "blur", yearUpdateHandler, this, true); | 
|  | E.on(this.monthEl, "change", monthUpdateHandler, this, true); | 
|  |  | 
|  | if (this.__isIEQuirks) { | 
|  | YAHOO.util.Event.on(this.cal.oDomContainer, "resize", this._syncMask, this, true); | 
|  | } | 
|  |  | 
|  | this.applyKeyListeners(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Removes/purges DOM event listeners from the rendered elements | 
|  | * | 
|  | * @method purgeListeners | 
|  | */ | 
|  | purgeListeners : function() { | 
|  | var E = YAHOO.util.Event; | 
|  | E.removeListener(this.submitEl, "click", this.submit); | 
|  | E.removeListener(this.cancelEl, "click", this.cancel); | 
|  | E.removeListener(this.yearEl, "blur"); | 
|  | E.removeListener(this.monthEl, "change"); | 
|  | if (this.__isIEQuirks) { | 
|  | E.removeListener(this.cal.oDomContainer, "resize", this._syncMask); | 
|  | } | 
|  |  | 
|  | this.purgeKeyListeners(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Attaches DOM listeners for keyboard support. | 
|  | * Tab/Shift-Tab looping, Enter Key Submit on Year element, | 
|  | * Up/Down/PgUp/PgDown year increment on Year element | 
|  | * <p> | 
|  | * NOTE: MacOSX Safari 2.x doesn't let you tab to buttons and | 
|  | * MacOSX Gecko does not let you tab to buttons or select controls, | 
|  | * so for these browsers, Tab/Shift-Tab looping is limited to the | 
|  | * elements which can be reached using the tab key. | 
|  | * </p> | 
|  | * @method applyKeyListeners | 
|  | */ | 
|  | applyKeyListeners : function() { | 
|  | var E = YAHOO.util.Event, | 
|  | ua = YAHOO.env.ua; | 
|  |  | 
|  | // IE/Safari 3.1 doesn't fire keypress for arrow/pg keys (non-char keys) | 
|  | var arrowEvt = (ua.ie || ua.webkit) ? "keydown" : "keypress"; | 
|  |  | 
|  | // - IE/Safari 3.1 doesn't fire keypress for non-char keys | 
|  | // - Opera doesn't allow us to cancel keydown or keypress for tab, but | 
|  | //   changes focus successfully on keydown (keypress is too late to change focus - opera's already moved on). | 
|  | var tabEvt = (ua.ie || ua.opera || ua.webkit) ? "keydown" : "keypress"; | 
|  |  | 
|  | // Everyone likes keypress for Enter (char keys) - whoo hoo! | 
|  | E.on(this.yearEl, "keypress", this._handleEnterKey, this, true); | 
|  |  | 
|  | E.on(this.yearEl, arrowEvt, this._handleDirectionKeys, this, true); | 
|  | E.on(this.lastCtrl, tabEvt, this._handleTabKey, this, true); | 
|  | E.on(this.firstCtrl, tabEvt, this._handleShiftTabKey, this, true); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Removes/purges DOM listeners for keyboard support | 
|  | * | 
|  | * @method purgeKeyListeners | 
|  | */ | 
|  | purgeKeyListeners : function() { | 
|  | var E = YAHOO.util.Event, | 
|  | ua = YAHOO.env.ua; | 
|  |  | 
|  | var arrowEvt = (ua.ie || ua.webkit) ? "keydown" : "keypress"; | 
|  | var tabEvt = (ua.ie || ua.opera || ua.webkit) ? "keydown" : "keypress"; | 
|  |  | 
|  | E.removeListener(this.yearEl, "keypress", this._handleEnterKey); | 
|  | E.removeListener(this.yearEl, arrowEvt, this._handleDirectionKeys); | 
|  | E.removeListener(this.lastCtrl, tabEvt, this._handleTabKey); | 
|  | E.removeListener(this.firstCtrl, tabEvt, this._handleShiftTabKey); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Updates the Calendar/CalendarGroup's pagedate with the currently set month and year if valid. | 
|  | * <p> | 
|  | * If the currently set month/year is invalid, a validation error will be displayed and the | 
|  | * Calendar/CalendarGroup's pagedate will not be updated. | 
|  | * </p> | 
|  | * @method submit | 
|  | */ | 
|  | submit : function() { | 
|  | if (this.validate()) { | 
|  | this.hide(); | 
|  |  | 
|  | this.setMonth(this._getMonthFromUI()); | 
|  | this.setYear(this._getYearFromUI()); | 
|  |  | 
|  | var cal = this.cal; | 
|  |  | 
|  | // Artificial delay, just to help the user see something changed | 
|  | var delay = YAHOO.widget.CalendarNavigator.UPDATE_DELAY; | 
|  | if (delay > 0) { | 
|  | var nav = this; | 
|  | window.setTimeout(function(){ nav._update(cal); }, delay); | 
|  | } else { | 
|  | this._update(cal); | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Updates the Calendar rendered state, based on the state of the CalendarNavigator | 
|  | * @method _update | 
|  | * @param cal The Calendar instance to update | 
|  | * @protected | 
|  | */ | 
|  | _update : function(cal) { | 
|  | cal.setYear(this.getYear()); | 
|  | cal.setMonth(this.getMonth()); | 
|  | cal.render(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Hides the navigator and mask, without updating the Calendar/CalendarGroup's state | 
|  | * | 
|  | * @method cancel | 
|  | */ | 
|  | cancel : function() { | 
|  | this.hide(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Validates the current state of the UI controls | 
|  | * | 
|  | * @method validate | 
|  | * @return {Boolean} true, if the current UI state contains valid values, false if not | 
|  | */ | 
|  | validate : function() { | 
|  | if (this._getYearFromUI() !== null) { | 
|  | this.clearErrors(); | 
|  | return true; | 
|  | } else { | 
|  | this.setYearError(); | 
|  | this.setError(this.__getCfg("invalidYear", true)); | 
|  | return false; | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Displays an error message in the Navigator's error panel | 
|  | * @method setError | 
|  | * @param {String} msg The error message to display | 
|  | */ | 
|  | setError : function(msg) { | 
|  | if (this.errorEl) { | 
|  | this.errorEl.innerHTML = msg; | 
|  | this._show(this.errorEl, true); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Clears the navigator's error message and hides the error panel | 
|  | * @method clearError | 
|  | */ | 
|  | clearError : function() { | 
|  | if (this.errorEl) { | 
|  | this.errorEl.innerHTML = ""; | 
|  | this._show(this.errorEl, false); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Displays the validation error UI for the year control | 
|  | * @method setYearError | 
|  | */ | 
|  | setYearError : function() { | 
|  | YAHOO.util.Dom.addClass(this.yearEl, YAHOO.widget.CalendarNavigator.CLASSES.INVALID); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Removes the validation error UI for the year control | 
|  | * @method clearYearError | 
|  | */ | 
|  | clearYearError : function() { | 
|  | YAHOO.util.Dom.removeClass(this.yearEl, YAHOO.widget.CalendarNavigator.CLASSES.INVALID); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Clears all validation and error messages in the UI | 
|  | * @method clearErrors | 
|  | */ | 
|  | clearErrors : function() { | 
|  | this.clearError(); | 
|  | this.clearYearError(); | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Sets the initial focus, based on the configured value | 
|  | * @method setInitialFocus | 
|  | */ | 
|  | setInitialFocus : function() { | 
|  | var el = this.submitEl, | 
|  | f = this.__getCfg("initialFocus"); | 
|  |  | 
|  | if (f && f.toLowerCase) { | 
|  | f = f.toLowerCase(); | 
|  | if (f == "year") { | 
|  | el = this.yearEl; | 
|  | try { | 
|  | this.yearEl.select(); | 
|  | } catch (selErr) { | 
|  | // Ignore; | 
|  | } | 
|  | } else if (f == "month") { | 
|  | el = this.monthEl; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (el && YAHOO.lang.isFunction(el.focus)) { | 
|  | try { | 
|  | el.focus(); | 
|  | } catch (focusErr) { | 
|  | // TODO: Fall back if focus fails? | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Removes all renderered HTML elements for the Navigator from | 
|  | * the DOM, purges event listeners and clears (nulls) any property | 
|  | * references to HTML references | 
|  | * @method erase | 
|  | */ | 
|  | erase : function() { | 
|  | if (this.__rendered) { | 
|  | this.purgeListeners(); | 
|  |  | 
|  | // Clear out innerHTML references | 
|  | this.yearEl = null; | 
|  | this.monthEl = null; | 
|  | this.errorEl = null; | 
|  | this.submitEl = null; | 
|  | this.cancelEl = null; | 
|  | this.firstCtrl = null; | 
|  | this.lastCtrl = null; | 
|  | if (this.navEl) { | 
|  | this.navEl.innerHTML = ""; | 
|  | } | 
|  |  | 
|  | var p = this.navEl.parentNode; | 
|  | if (p) { | 
|  | p.removeChild(this.navEl); | 
|  | } | 
|  | this.navEl = null; | 
|  |  | 
|  | var pm = this.maskEl.parentNode; | 
|  | if (pm) { | 
|  | pm.removeChild(this.maskEl); | 
|  | } | 
|  | this.maskEl = null; | 
|  | this.__rendered = false; | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Destroys the Navigator object and any HTML references | 
|  | * @method destroy | 
|  | */ | 
|  | destroy : function() { | 
|  | this.erase(); | 
|  | this._doc = null; | 
|  | this.cal = null; | 
|  | this.id = null; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Protected implementation to handle how UI elements are | 
|  | * hidden/shown. | 
|  | * | 
|  | * @method _show | 
|  | * @protected | 
|  | */ | 
|  | _show : function(el, bShow) { | 
|  | if (el) { | 
|  | YAHOO.util.Dom.setStyle(el, "display", (bShow) ? "block" : "none"); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Returns the month value (index), from the month UI element | 
|  | * @protected | 
|  | * @method _getMonthFromUI | 
|  | * @return {Number} The month index, or 0 if a UI element for the month | 
|  | * is not found | 
|  | */ | 
|  | _getMonthFromUI : function() { | 
|  | if (this.monthEl) { | 
|  | return this.monthEl.selectedIndex; | 
|  | } else { | 
|  | return 0; // Default to Jan | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Returns the year value, from the Navitator's year UI element | 
|  | * @protected | 
|  | * @method _getYearFromUI | 
|  | * @return {Number} The year value set in the UI, if valid. null is returned if | 
|  | * the UI does not contain a valid year value. | 
|  | */ | 
|  | _getYearFromUI : function() { | 
|  | var NAV = YAHOO.widget.CalendarNavigator; | 
|  |  | 
|  | var yr = null; | 
|  | if (this.yearEl) { | 
|  | var value = this.yearEl.value; | 
|  | value = value.replace(NAV.TRIM, "$1"); | 
|  |  | 
|  | if (NAV.YR_PATTERN.test(value)) { | 
|  | yr = parseInt(value, 10); | 
|  | } | 
|  | } | 
|  | return yr; | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Updates the Navigator's year UI, based on the year value set on the Navigator object | 
|  | * @protected | 
|  | * @method _updateYearUI | 
|  | */ | 
|  | _updateYearUI : function() { | 
|  | if (this.yearEl && this._year !== null) { | 
|  | this.yearEl.value = this._year; | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Updates the Navigator's month UI, based on the month value set on the Navigator object | 
|  | * @protected | 
|  | * @method _updateMonthUI | 
|  | */ | 
|  | _updateMonthUI : function() { | 
|  | if (this.monthEl) { | 
|  | this.monthEl.selectedIndex = this._month; | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Sets up references to the first and last focusable element in the Navigator's UI | 
|  | * in terms of tab order (Naviagator's firstEl and lastEl properties). The references | 
|  | * are used to control modality by looping around from the first to the last control | 
|  | * and visa versa for tab/shift-tab navigation. | 
|  | * <p> | 
|  | * See <a href="#applyKeyListeners">applyKeyListeners</a> | 
|  | * </p> | 
|  | * @protected | 
|  | * @method _setFirstLastElements | 
|  | */ | 
|  | _setFirstLastElements : function() { | 
|  | this.firstCtrl = this.monthEl; | 
|  | this.lastCtrl = this.cancelEl; | 
|  |  | 
|  | // Special handling for MacOSX. | 
|  | // - Safari 2.x can't focus on buttons | 
|  | // - Gecko can't focus on select boxes or buttons | 
|  | if (this.__isMac) { | 
|  | if (YAHOO.env.ua.webkit && YAHOO.env.ua.webkit < 420){ | 
|  | this.firstCtrl = this.monthEl; | 
|  | this.lastCtrl = this.yearEl; | 
|  | } | 
|  | if (YAHOO.env.ua.gecko) { | 
|  | this.firstCtrl = this.yearEl; | 
|  | this.lastCtrl = this.yearEl; | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Default Keyboard event handler to capture Enter | 
|  | * on the Navigator's year control (yearEl) | 
|  | * | 
|  | * @method _handleEnterKey | 
|  | * @protected | 
|  | * @param {Event} e The DOM event being handled | 
|  | */ | 
|  | _handleEnterKey : function(e) { | 
|  | var KEYS = YAHOO.util.KeyListener.KEY; | 
|  |  | 
|  | if (YAHOO.util.Event.getCharCode(e) == KEYS.ENTER) { | 
|  | YAHOO.util.Event.preventDefault(e); | 
|  | this.submit(); | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Default Keyboard event handler to capture up/down/pgup/pgdown | 
|  | * on the Navigator's year control (yearEl). | 
|  | * | 
|  | * @method _handleDirectionKeys | 
|  | * @protected | 
|  | * @param {Event} e The DOM event being handled | 
|  | */ | 
|  | _handleDirectionKeys : function(e) { | 
|  | var E = YAHOO.util.Event, | 
|  | KEYS = YAHOO.util.KeyListener.KEY, | 
|  | NAV = YAHOO.widget.CalendarNavigator; | 
|  |  | 
|  | var value = (this.yearEl.value) ? parseInt(this.yearEl.value, 10) : null; | 
|  | if (isFinite(value)) { | 
|  | var dir = false; | 
|  | switch(E.getCharCode(e)) { | 
|  | case KEYS.UP: | 
|  | this.yearEl.value = value + NAV.YR_MINOR_INC; | 
|  | dir = true; | 
|  | break; | 
|  | case KEYS.DOWN: | 
|  | this.yearEl.value = Math.max(value - NAV.YR_MINOR_INC, 0); | 
|  | dir = true; | 
|  | break; | 
|  | case KEYS.PAGE_UP: | 
|  | this.yearEl.value = value + NAV.YR_MAJOR_INC; | 
|  | dir = true; | 
|  | break; | 
|  | case KEYS.PAGE_DOWN: | 
|  | this.yearEl.value = Math.max(value - NAV.YR_MAJOR_INC, 0); | 
|  | dir = true; | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | if (dir) { | 
|  | E.preventDefault(e); | 
|  | try { | 
|  | this.yearEl.select(); | 
|  | } catch(err) { | 
|  | // Ignore | 
|  | } | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Default Keyboard event handler to capture Tab | 
|  | * on the last control (lastCtrl) in the Navigator. | 
|  | * | 
|  | * @method _handleTabKey | 
|  | * @protected | 
|  | * @param {Event} e The DOM event being handled | 
|  | */ | 
|  | _handleTabKey : function(e) { | 
|  | var E = YAHOO.util.Event, | 
|  | KEYS = YAHOO.util.KeyListener.KEY; | 
|  |  | 
|  | if (E.getCharCode(e) == KEYS.TAB && !e.shiftKey) { | 
|  | try { | 
|  | E.preventDefault(e); | 
|  | this.firstCtrl.focus(); | 
|  | } catch (err) { | 
|  | // Ignore - mainly for focus edge cases | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Default Keyboard event handler to capture Shift-Tab | 
|  | * on the first control (firstCtrl) in the Navigator. | 
|  | * | 
|  | * @method _handleShiftTabKey | 
|  | * @protected | 
|  | * @param {Event} e The DOM event being handled | 
|  | */ | 
|  | _handleShiftTabKey : function(e) { | 
|  | var E = YAHOO.util.Event, | 
|  | KEYS = YAHOO.util.KeyListener.KEY; | 
|  |  | 
|  | if (e.shiftKey && E.getCharCode(e) == KEYS.TAB) { | 
|  | try { | 
|  | E.preventDefault(e); | 
|  | this.lastCtrl.focus(); | 
|  | } catch (err) { | 
|  | // Ignore - mainly for focus edge cases | 
|  | } | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Retrieve Navigator configuration values from | 
|  | * the parent Calendar/CalendarGroup's config value. | 
|  | * <p> | 
|  | * If it has not been set in the user provided configuration, the method will | 
|  | * return the default value of the configuration property, as set in _DEFAULT_CFG | 
|  | * </p> | 
|  | * @private | 
|  | * @method __getCfg | 
|  | * @param {String} Case sensitive property name. | 
|  | * @param {Boolean} true, if the property is a string property, false if not. | 
|  | * @return The value of the configuration property | 
|  | */ | 
|  | __getCfg : function(prop, bIsStr) { | 
|  | var DEF_CFG = YAHOO.widget.CalendarNavigator._DEFAULT_CFG; | 
|  | var cfg = this.cal.cfg.getProperty("navigator"); | 
|  |  | 
|  | if (bIsStr) { | 
|  | return (cfg !== true && cfg.strings && cfg.strings[prop]) ? cfg.strings[prop] : DEF_CFG.strings[prop]; | 
|  | } else { | 
|  | return (cfg !== true && cfg[prop]) ? cfg[prop] : DEF_CFG[prop]; | 
|  | } | 
|  | }, | 
|  |  | 
|  | /** | 
|  | * Private flag, to identify MacOS | 
|  | * @private | 
|  | * @property __isMac | 
|  | */ | 
|  | __isMac : (navigator.userAgent.toLowerCase().indexOf("macintosh") != -1) | 
|  |  | 
|  | }; | 
|  |  | 
|  | YAHOO.register("calendar", YAHOO.widget.Calendar, {version: "2.6.0", build: "1321"}); |