/* Copyright (c) 2007, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 2.3.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); } if (!owner) { YAHOO.log("No owner specified for Config object", "error"); } }; 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 ) { YAHOO.log("Firing Config event: " + key + "=" + value, "info"); 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(); YAHOO.log("Added property: " + key, "info"); 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 = {}, prop, property; for (prop in this.config) { property = this.config[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(); YAHOO.log("setProperty: " + key + "=" + value, "info"); 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(); YAHOO.log("queueProperty: " + key + "=" + value, "info"); 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; } } } } } YAHOO.log("Config event queue: " + this.outputEventQueue(), "info"); 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 prop; if (init) { this.initialConfig = userConfig; } for (prop in userConfig) { this.queueProperty(prop, userConfig[prop]); } }, /** * Refires the events for all configuration properties using their * current values. * @method refresh */ refresh: function () { var prop; for (prop in this.config) { 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, /** * 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: d.setDate(date.getDate() + amount); break; case this.YEAR: d.setFullYear(date.getFullYear() + amount); break; case this.WEEK: d.setDate(date.getDate() + (amount * 7)); break; } return d; }, /** * 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 new Date(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. This function assumes that week 1 is the * week in which January 1 appears, regardless of whether the week consists of a full 7 days. * The calendar year can be specified to help find what a the week number would be for a given * date if the date overlaps years. For instance, a week may be considered week 1 of 2005, or * week 53 of 2004. Specifying the optional calendarYear allows one to make this distinction * easily. * @method getWeekNumber * @param {Date} date The JavaScript date for which to find the week number * @param {Number} calendarYear OPTIONAL - The calendar year to use for determining the week number. Default is * the calendar year of parameter "date". * @return {Number} The week number of the given date. */ getWeekNumber : function(date, calendarYear) { date = this.clearTime(date); var nearestThurs = new Date(date.getTime() + (4 * this.ONE_DAY_MS) - ((date.getDay()) * this.ONE_DAY_MS)); var jan1 = new Date(nearestThurs.getFullYear(),0,1); var dayOfYear = ((nearestThurs.getTime() - jan1.getTime()) / this.ONE_DAY_MS) - 1; var weekNum = Math.ceil((dayOfYear)/ 7); return weekNum; }, /** * 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 = new Date(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; } }; /** * 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 */ /** * 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. *

To construct the placeholder for the calendar widget, the code is as * follows: *

* <div id="cal1Container"></div> * *

* @namespace YAHOO.widget * @class Calendar * @constructor * @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 */ YAHOO.widget.Calendar = function(id, containerId, config) { this.init(id, containerId, config); }; /** * 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 */ YAHOO.widget.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 */ YAHOO.widget.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 */ YAHOO.widget.Calendar.MONTH_DAY = "MD"; /** * Type constant used for renderers to represent a weekday * @property YAHOO.widget.Calendar.WEEKDAY * @static * @final * @type String */ YAHOO.widget.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 */ YAHOO.widget.Calendar.RANGE = "R"; /** * Type constant used for renderers to represent a month across any year * @property YAHOO.widget.Calendar.MONTH * @static * @final * @type String */ YAHOO.widget.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 */ YAHOO.widget.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 */ YAHOO.widget.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 */ YAHOO.widget.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 */ YAHOO.widget.Calendar.LONG = "long"; /** * Constant used to represent medium date field string formats (e.g. Mon) * @property YAHOO.widget.Calendar.MEDIUM * @static * @final * @type String */ YAHOO.widget.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 */ YAHOO.widget.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 */ YAHOO.widget.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:""} }; /** * The set of Custom Event types supported by the Calendar * @property YAHOO.widget.Calendar._EVENT_TYPES * @final * @static * @private * @type Object */ YAHOO.widget.Calendar._EVENT_TYPES = { BEFORE_SELECT : "beforeSelect", SELECT : "select", BEFORE_DESELECT : "beforeDeselect", DESELECT : "deselect", CHANGE_PAGE : "changePage", BEFORE_RENDER : "beforeRender", RENDER : "render", RESET : "reset", CLEAR : "clear" }; /** * The set of default style constants for the Calendar * @property YAHOO.widget.Calendar._STYLES * @final * @static * @private * @type Object */ YAHOO.widget.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_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" }; YAHOO.widget.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. This id should match the id of the placeholder element on the page. * @property id * @type String */ id : 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, /** * 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 }; /** * Initializes the Calendar widget. * @method init * @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 */ YAHOO.widget.Calendar.prototype.init = function(id, containerId, config) { this.logger = new YAHOO.widget.LogWriter("Calendar " + id); this.initEvents(); this.today = new Date(); YAHOO.widget.DateMath.clearTime(this.today); this.id = id; this.oDomContainer = document.getElementById(containerId); if (! this.oDomContainer) { this.logger.log("No valid container present.", "error"); } /** * 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(); YAHOO.util.Dom.addClass(this.oDomContainer, this.Style.CSS_CONTAINER); YAHOO.util.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 */ YAHOO.widget.Calendar.prototype.configIframe = function(type, args, obj) { var useIframe = args[0]; if (!this.parent) { if (YAHOO.util.Dom.inDocument(this.oDomContainer)) { if (useIframe) { var pos = YAHOO.util.Dom.getStyle(this.oDomContainer, "position"); if (pos == "absolute" || pos == "relative") { if (!YAHOO.util.Dom.inDocument(this.iframe)) { this.iframe = document.createElement("iframe"); this.iframe.src = "javascript:false;"; YAHOO.util.Dom.setStyle(this.iframe, "opacity", "0"); if (YAHOO.env.ua.ie && YAHOO.env.ua.ie <= 6) { YAHOO.util.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 */ YAHOO.widget.Calendar.prototype.configTitle = function(type, args, obj) { var title = args[0]; var close = this.cfg.getProperty(YAHOO.widget.Calendar._DEFAULT_CONFIG.CLOSE.key); var titleDiv; if (title && title !== "") { titleDiv = YAHOO.util.Dom.getElementsByClassName(YAHOO.widget.CalendarGroup.CSS_2UPTITLE, "div", this.oDomContainer)[0] || document.createElement("div"); titleDiv.className = YAHOO.widget.CalendarGroup.CSS_2UPTITLE; titleDiv.innerHTML = title; this.oDomContainer.insertBefore(titleDiv, this.oDomContainer.firstChild); YAHOO.util.Dom.addClass(this.oDomContainer, "withtitle"); } else { titleDiv = YAHOO.util.Dom.getElementsByClassName(YAHOO.widget.CalendarGroup.CSS_2UPTITLE, "div", this.oDomContainer)[0] || null; if (titleDiv) { YAHOO.util.Event.purgeElement(titleDiv); this.oDomContainer.removeChild(titleDiv); } if (! close) { YAHOO.util.Dom.removeClass(this.oDomContainer, "withtitle"); } } }; /** * Default handler for the "close" property * @method configClose */ YAHOO.widget.Calendar.prototype.configClose = function(type, args, obj) { var close = args[0]; var title = this.cfg.getProperty(YAHOO.widget.Calendar._DEFAULT_CONFIG.TITLE.key); var DEPR_CLOSE_PATH = "us/my/bn/x_d.gif"; var linkClose; if (close === true) { linkClose = YAHOO.util.Dom.getElementsByClassName("link-close", "a", this.oDomContainer)[0] || document.createElement("a"); linkClose.href = "#"; linkClose.className = "link-close"; YAHOO.util.Event.addListener(linkClose, "click", function(e, cal) {cal.hide(); YAHOO.util.Event.preventDefault(e); }, this); if (YAHOO.widget.Calendar.IMG_ROOT !== null) { var imgClose = document.createElement("img"); imgClose.src = YAHOO.widget.Calendar.IMG_ROOT + DEPR_CLOSE_PATH; imgClose.className = YAHOO.widget.CalendarGroup.CSS_2UPCLOSE; linkClose.appendChild(imgClose); } else { linkClose.innerHTML = ''; } this.oDomContainer.appendChild(linkClose); YAHOO.util.Dom.addClass(this.oDomContainer, "withtitle"); } else { linkClose = YAHOO.util.Dom.getElementsByClassName("link-close", "a", this.oDomContainer)[0] || null; if (linkClose) { YAHOO.util.Event.purgeElement(linkClose); this.oDomContainer.removeChild(linkClose); } if (! title || title === "") { YAHOO.util.Dom.removeClass(this.oDomContainer, "withtitle"); } } }; /** * Initializes Calendar's built-in CustomEvents * @method initEvents */ YAHOO.widget.Calendar.prototype.initEvents = function() { var defEvents = YAHOO.widget.Calendar._EVENT_TYPES; /** * Fired before a selection is made * @event beforeSelectEvent */ this.beforeSelectEvent = new YAHOO.util.CustomEvent(defEvents.BEFORE_SELECT); /** * Fired when a selection is made * @event selectEvent * @param {Array} Array of Date field arrays in the format [YYYY, MM, DD]. */ this.selectEvent = new YAHOO.util.CustomEvent(defEvents.SELECT); /** * Fired before a selection is made * @event beforeDeselectEvent */ this.beforeDeselectEvent = new YAHOO.util.CustomEvent(defEvents.BEFORE_DESELECT); /** * Fired when a selection is made * @event deselectEvent * @param {Array} Array of Date field arrays in the format [YYYY, MM, DD]. */ this.deselectEvent = new YAHOO.util.CustomEvent(defEvents.DESELECT); /** * Fired when the Calendar page is changed * @event changePageEvent */ this.changePageEvent = new YAHOO.util.CustomEvent(defEvents.CHANGE_PAGE); /** * Fired before the Calendar is rendered * @event beforeRenderEvent */ this.beforeRenderEvent = new YAHOO.util.CustomEvent(defEvents.BEFORE_RENDER); /** * Fired when the Calendar is rendered * @event renderEvent */ this.renderEvent = new YAHOO.util.CustomEvent(defEvents.RENDER); /** * Fired when the Calendar is reset * @event resetEvent */ this.resetEvent = new YAHOO.util.CustomEvent(defEvents.RESET); /** * Fired when the Calendar is cleared * @event clearEvent */ this.clearEvent = new YAHOO.util.CustomEvent(defEvents.CLEAR); this.beforeSelectEvent.subscribe(this.onBeforeSelect, this, true); this.selectEvent.subscribe(this.onSelect, this, true); this.beforeDeselectEvent.subscribe(this.onBeforeDeselect, this, true); this.deselectEvent.subscribe(this.onDeselect, this, true); this.changePageEvent.subscribe(this.onChangePage, this, true); this.renderEvent.subscribe(this.onRender, this, true); this.resetEvent.subscribe(this.onReset, this, true); this.clearEvent.subscribe(this.onClear, this, true); }; /** * The default event function that is attached to a date link within a calendar cell * when the calendar is rendered. * @method doSelectCell * @param {DOMEvent} e The event * @param {Calendar} cal A reference to the calendar passed by the Event utility */ YAHOO.widget.Calendar.prototype.doSelectCell = function(e, cal) { var cell,index,d,date; var target = YAHOO.util.Event.getTarget(e); var tagName = target.tagName.toLowerCase(); var defSelector = false; while (tagName != "td" && ! YAHOO.util.Dom.hasClass(target, cal.Style.CSS_CELL_SELECTABLE)) { if (!defSelector && tagName == "a" && YAHOO.util.Dom.hasClass(target, cal.Style.CSS_CELL_SELECTOR)) { defSelector = true; } target = target.parentNode; tagName = target.tagName.toLowerCase(); if (tagName == "html") { return; } } if (defSelector) { // Stop link href navigation for default renderer YAHOO.util.Event.preventDefault(e); } cell = target; if (YAHOO.util.Dom.hasClass(cell, cal.Style.CSS_CELL_SELECTABLE)) { index = cell.id.split("cell")[1]; d = cal.cellDates[index]; date = new Date(d[0],d[1]-1,d[2]); var link; cal.logger.log("Selecting cell " + index + " via click", "info"); 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 */ YAHOO.widget.Calendar.prototype.doCellMouseOver = function(e, cal) { var target; if (e) { target = YAHOO.util.Event.getTarget(e); } else { target = this; } while (target.tagName.toLowerCase() != "td") { target = target.parentNode; if (target.tagName.toLowerCase() == "html") { return; } } if (YAHOO.util.Dom.hasClass(target, cal.Style.CSS_CELL_SELECTABLE)) { YAHOO.util.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 */ YAHOO.widget.Calendar.prototype.doCellMouseOut = function(e, cal) { var target; if (e) { target = YAHOO.util.Event.getTarget(e); } else { target = this; } while (target.tagName.toLowerCase() != "td") { target = target.parentNode; if (target.tagName.toLowerCase() == "html") { return; } } if (YAHOO.util.Dom.hasClass(target, cal.Style.CSS_CELL_SELECTABLE)) { YAHOO.util.Dom.removeClass(target, cal.Style.CSS_CELL_HOVER); } }; YAHOO.widget.Calendar.prototype.setupConfig = function() { var defCfg = YAHOO.widget.Calendar._DEFAULT_CONFIG; /** * The month/year representing the current visible Calendar date (mm/yyyy) * @config pagedate * @type String * @default today's date */ this.cfg.addProperty(defCfg.PAGEDATE.key, { value:new Date(), handler:this.configPageDate } ); /** * The date or range of dates representing the current Calendar selection * @config selected * @type String * @default [] */ this.cfg.addProperty(defCfg.SELECTED.key, { value:[], handler:this.configSelected } ); /** * The title to display above the Calendar's month header * @config title * @type String * @default "" */ this.cfg.addProperty(defCfg.TITLE.key, { value:defCfg.TITLE.value, handler:this.configTitle } ); /** * Whether or not a close button should be displayed for this Calendar * @config close * @type Boolean * @default false */ this.cfg.addProperty(defCfg.CLOSE.key, { value:defCfg.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 */ this.cfg.addProperty(defCfg.IFRAME.key, { value:defCfg.IFRAME.value, handler:this.configIframe, validator:this.cfg.checkBoolean } ); /** * The minimum selectable date in the current Calendar (mm/dd/yyyy) * @config mindate * @type String * @default null */ this.cfg.addProperty(defCfg.MINDATE.key, { value:defCfg.MINDATE.value, handler:this.configMinDate } ); /** * The maximum selectable date in the current Calendar (mm/dd/yyyy) * @config maxdate * @type String * @default null */ this.cfg.addProperty(defCfg.MAXDATE.key, { value:defCfg.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 */ this.cfg.addProperty(defCfg.MULTI_SELECT.key, { value:defCfg.MULTI_SELECT.value, handler:this.configOptions, validator:this.cfg.checkBoolean } ); /** * The weekday the week begins on. Default is 0 (Sunday). * @config START_WEEKDAY * @type number * @default 0 */ this.cfg.addProperty(defCfg.START_WEEKDAY.key, { value:defCfg.START_WEEKDAY.value, handler:this.configOptions, validator:this.cfg.checkNumber } ); /** * True if the Calendar should show weekday labels. True by default. * @config SHOW_WEEKDAYS * @type Boolean * @default true */ this.cfg.addProperty(defCfg.SHOW_WEEKDAYS.key, { value:defCfg.SHOW_WEEKDAYS.value, handler:this.configOptions, validator:this.cfg.checkBoolean } ); /** * True if the Calendar should show week row headers. False by default. * @config SHOW_WEEK_HEADER * @type Boolean * @default false */ this.cfg.addProperty(defCfg.SHOW_WEEK_HEADER.key, { value:defCfg.SHOW_WEEK_HEADER.value, handler:this.configOptions, validator:this.cfg.checkBoolean } ); /** * True if the Calendar should show week row footers. False by default. * @config SHOW_WEEK_FOOTER * @type Boolean * @default false */ this.cfg.addProperty(defCfg.SHOW_WEEK_FOOTER.key,{ value:defCfg.SHOW_WEEK_FOOTER.value, handler:this.configOptions, validator:this.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 */ this.cfg.addProperty(defCfg.HIDE_BLANK_WEEKS.key, { value:defCfg.HIDE_BLANK_WEEKS.value, handler:this.configOptions, validator:this.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 */ this.cfg.addProperty(defCfg.NAV_ARROW_LEFT.key, { value:defCfg.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 */ this.cfg.addProperty(defCfg.NAV_ARROW_RIGHT.key, { value:defCfg.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"] */ this.cfg.addProperty(defCfg.MONTHS_SHORT.key, { value:defCfg.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" */ this.cfg.addProperty(defCfg.MONTHS_LONG.key, { value:defCfg.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"] */ this.cfg.addProperty(defCfg.WEEKDAYS_1CHAR.key, { value:defCfg.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"] */ this.cfg.addProperty(defCfg.WEEKDAYS_SHORT.key, { value:defCfg.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"] */ this.cfg.addProperty(defCfg.WEEKDAYS_MEDIUM.key, { value:defCfg.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"] */ this.cfg.addProperty(defCfg.WEEKDAYS_LONG.key, { value:defCfg.WEEKDAYS_LONG.value, handler:this.configLocale } ); /** * Refreshes the locale values used to build the Calendar. * @method refreshLocale * @private */ var refreshLocale = function() { this.cfg.refireEvent(defCfg.LOCALE_MONTHS.key); this.cfg.refireEvent(defCfg.LOCALE_WEEKDAYS.key); }; this.cfg.subscribeToConfigEvent(defCfg.START_WEEKDAY.key, refreshLocale, this, true); this.cfg.subscribeToConfigEvent(defCfg.MONTHS_SHORT.key, refreshLocale, this, true); this.cfg.subscribeToConfigEvent(defCfg.MONTHS_LONG.key, refreshLocale, this, true); this.cfg.subscribeToConfigEvent(defCfg.WEEKDAYS_1CHAR.key, refreshLocale, this, true); this.cfg.subscribeToConfigEvent(defCfg.WEEKDAYS_SHORT.key, refreshLocale, this, true); this.cfg.subscribeToConfigEvent(defCfg.WEEKDAYS_MEDIUM.key, refreshLocale, this, true); this.cfg.subscribeToConfigEvent(defCfg.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" */ this.cfg.addProperty(defCfg.LOCALE_MONTHS.key, { value:defCfg.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" */ this.cfg.addProperty(defCfg.LOCALE_WEEKDAYS.key, { value:defCfg.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 "," */ this.cfg.addProperty(defCfg.DATE_DELIMITER.key, { value:defCfg.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 "/" */ this.cfg.addProperty(defCfg.DATE_FIELD_DELIMITER.key, { value:defCfg.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 "-" */ this.cfg.addProperty(defCfg.DATE_RANGE_DELIMITER.key, { value:defCfg.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 */ this.cfg.addProperty(defCfg.MY_MONTH_POSITION.key, { value:defCfg.MY_MONTH_POSITION.value, handler:this.configLocale, validator:this.cfg.checkNumber } ); /** * The position of the year in a month/year date string * @config MY_YEAR_POSITION * @type Number * @default 2 */ this.cfg.addProperty(defCfg.MY_YEAR_POSITION.key, { value:defCfg.MY_YEAR_POSITION.value, handler:this.configLocale, validator:this.cfg.checkNumber } ); /** * The position of the month in a month/day date string * @config MD_MONTH_POSITION * @type Number * @default 1 */ this.cfg.addProperty(defCfg.MD_MONTH_POSITION.key, { value:defCfg.MD_MONTH_POSITION.value, handler:this.configLocale, validator:this.cfg.checkNumber } ); /** * The position of the day in a month/year date string * @config MD_DAY_POSITION * @type Number * @default 2 */ this.cfg.addProperty(defCfg.MD_DAY_POSITION.key, { value:defCfg.MD_DAY_POSITION.value, handler:this.configLocale, validator:this.cfg.checkNumber } ); /** * The position of the month in a month/day/year date string * @config MDY_MONTH_POSITION * @type Number * @default 1 */ this.cfg.addProperty(defCfg.MDY_MONTH_POSITION.key, { value:defCfg.MDY_MONTH_POSITION.value, handler:this.configLocale, validator:this.cfg.checkNumber } ); /** * The position of the day in a month/day/year date string * @config MDY_DAY_POSITION * @type Number * @default 2 */ this.cfg.addProperty(defCfg.MDY_DAY_POSITION.key, { value:defCfg.MDY_DAY_POSITION.value, handler:this.configLocale, validator:this.cfg.checkNumber } ); /** * The position of the year in a month/day/year date string * @config MDY_YEAR_POSITION * @type Number * @default 3 */ this.cfg.addProperty(defCfg.MDY_YEAR_POSITION.key, { value:defCfg.MDY_YEAR_POSITION.value, handler:this.configLocale, validator:this.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 */ this.cfg.addProperty(defCfg.MY_LABEL_MONTH_POSITION.key, { value:defCfg.MY_LABEL_MONTH_POSITION.value, handler:this.configLocale, validator:this.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 */ this.cfg.addProperty(defCfg.MY_LABEL_YEAR_POSITION.key, { value:defCfg.MY_LABEL_YEAR_POSITION.value, handler:this.configLocale, validator:this.cfg.checkNumber } ); /** * The suffix used after the month when rendering the Calendar header * @config MY_LABEL_MONTH_SUFFIX * @type String * @default " " */ this.cfg.addProperty(defCfg.MY_LABEL_MONTH_SUFFIX.key, { value:defCfg.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 "" */ this.cfg.addProperty(defCfg.MY_LABEL_YEAR_SUFFIX.key, { value:defCfg.MY_LABEL_YEAR_SUFFIX.value, handler:this.configLocale } ); }; /** * The default handler for the "pagedate" property * @method configPageDate */ YAHOO.widget.Calendar.prototype.configPageDate = function(type, args, obj) { this.cfg.setProperty(YAHOO.widget.Calendar._DEFAULT_CONFIG.PAGEDATE.key, this._parsePageDate(args[0]), true); }; /** * The default handler for the "mindate" property * @method configMinDate */ YAHOO.widget.Calendar.prototype.configMinDate = function(type, args, obj) { var val = args[0]; if (YAHOO.lang.isString(val)) { val = this._parseDate(val); this.cfg.setProperty(YAHOO.widget.Calendar._DEFAULT_CONFIG.MINDATE.key, new Date(val[0],(val[1]-1),val[2])); } }; /** * The default handler for the "maxdate" property * @method configMaxDate */ YAHOO.widget.Calendar.prototype.configMaxDate = function(type, args, obj) { var val = args[0]; if (YAHOO.lang.isString(val)) { val = this._parseDate(val); this.cfg.setProperty(YAHOO.widget.Calendar._DEFAULT_CONFIG.MAXDATE.key, new Date(val[0],(val[1]-1),val[2])); } }; /** * The default handler for the "selected" property * @method configSelected */ YAHOO.widget.Calendar.prototype.configSelected = function(type, args, obj) { var selected = args[0]; var cfgSelected = YAHOO.widget.Calendar._DEFAULT_CONFIG.SELECTED.key; if (selected) { if (YAHOO.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 */ YAHOO.widget.Calendar.prototype.configOptions = function(type, args, obj) { this.Options[type.toUpperCase()] = args[0]; }; /** * The default handler for all configuration locale properties * @method configLocale */ YAHOO.widget.Calendar.prototype.configLocale = function(type, args, obj) { var defCfg = YAHOO.widget.Calendar._DEFAULT_CONFIG; this.Locale[type.toUpperCase()] = args[0]; this.cfg.refireEvent(defCfg.LOCALE_MONTHS.key); this.cfg.refireEvent(defCfg.LOCALE_WEEKDAYS.key); }; /** * The default handler for all configuration locale field length properties * @method configLocaleValues */ YAHOO.widget.Calendar.prototype.configLocaleValues = function(type, args, obj) { var defCfg = YAHOO.widget.Calendar._DEFAULT_CONFIG; type = type.toLowerCase(); var val = args[0]; switch (type) { case defCfg.LOCALE_MONTHS.key: switch (val) { case YAHOO.widget.Calendar.SHORT: this.Locale.LOCALE_MONTHS = this.cfg.getProperty(defCfg.MONTHS_SHORT.key).concat(); break; case YAHOO.widget.Calendar.LONG: this.Locale.LOCALE_MONTHS = this.cfg.getProperty(defCfg.MONTHS_LONG.key).concat(); break; } break; case defCfg.LOCALE_WEEKDAYS.key: switch (val) { case YAHOO.widget.Calendar.ONE_CHAR: this.Locale.LOCALE_WEEKDAYS = this.cfg.getProperty(defCfg.WEEKDAYS_1CHAR.key).concat(); break; case YAHOO.widget.Calendar.SHORT: this.Locale.LOCALE_WEEKDAYS = this.cfg.getProperty(defCfg.WEEKDAYS_SHORT.key).concat(); break; case YAHOO.widget.Calendar.MEDIUM: this.Locale.LOCALE_WEEKDAYS = this.cfg.getProperty(defCfg.WEEKDAYS_MEDIUM.key).concat(); break; case YAHOO.widget.Calendar.LONG: this.Locale.LOCALE_WEEKDAYS = this.cfg.getProperty(defCfg.WEEKDAYS_LONG.key).concat(); break; } var START_WEEKDAY = this.cfg.getProperty(defCfg.START_WEEKDAY.key); if (START_WEEKDAY > 0) { for (var w=0;w'; html[html.length] = '
'; 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; } var cal = this.parent || this; if (renderLeft) { var leftArrow = this.cfg.getProperty(defCfg.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 && YAHOO.widget.Calendar.IMG_ROOT !== null) { leftArrow = YAHOO.widget.Calendar.IMG_ROOT + DEPR_NAV_LEFT; } var leftStyle = (leftArrow === null) ? "" : ' style="background-image:url(' + leftArrow + ')"'; html[html.length] = ' '; } html[html.length] = this.buildMonthLabel(); if (renderRight) { var rightArrow = this.cfg.getProperty(defCfg.NAV_ARROW_RIGHT.key); if (rightArrow === null && YAHOO.widget.Calendar.IMG_ROOT !== null) { rightArrow = YAHOO.widget.Calendar.IMG_ROOT + DEPR_NAV_RIGHT; } var rightStyle = (rightArrow === null) ? "" : ' style="background-image:url(' + rightArrow + ')"'; html[html.length] = ' '; } html[html.length] = '
\n\n'; if (this.cfg.getProperty(defCfg.SHOW_WEEKDAYS.key)) { html = this.buildWeekdays(html); } html[html.length] = ''; 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 */ YAHOO.widget.Calendar.prototype.buildWeekdays = function(html) { var defCfg = YAHOO.widget.Calendar._DEFAULT_CONFIG; html[html.length] = ''; if (this.cfg.getProperty(defCfg.SHOW_WEEK_HEADER.key)) { html[html.length] = ' '; } for(var i=0;i'; } if (this.cfg.getProperty(defCfg.SHOW_WEEK_FOOTER.key)) { html[html.length] = ' '; } html[html.length] = ''; 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 */ YAHOO.widget.Calendar.prototype.renderBody = function(workingDate, html) { this.logger.log("Rendering body", "info"); var defCfg = YAHOO.widget.Calendar._DEFAULT_CONFIG; var startDay = this.cfg.getProperty(defCfg.START_WEEKDAY.key); this.preMonthDays = workingDate.getDay(); if (startDay > 0) { this.preMonthDays -= startDay; } if (this.preMonthDays < 0) { this.preMonthDays += 7; } this.monthDays = YAHOO.widget.DateMath.findMonthEnd(workingDate).getDate(); this.postMonthDays = YAHOO.widget.Calendar.DISPLAY_DAYS-this.preMonthDays-this.monthDays; this.logger.log(this.preMonthDays + " preciding out-of-month days", "info"); this.logger.log(this.monthDays + " month days", "info"); this.logger.log(this.postMonthDays + " post-month days", "info"); workingDate = YAHOO.widget.DateMath.subtract(workingDate, YAHOO.widget.DateMath.DAY, this.preMonthDays); this.logger.log("Calendar page starts on " + workingDate, "info"); var weekNum,weekClass; var weekPrefix = "w"; var cellPrefix = "_cell"; var workingDayPrefix = "wd"; var dayPrefix = "d"; var cellRenderers; var renderer; var todayYear = this.today.getFullYear(); var todayMonth = this.today.getMonth(); var todayDate = this.today.getDate(); var useDate = this.cfg.getProperty(defCfg.PAGEDATE.key); var hideBlankWeeks = this.cfg.getProperty(defCfg.HIDE_BLANK_WEEKS.key); var showWeekFooter = this.cfg.getProperty(defCfg.SHOW_WEEK_FOOTER.key); var showWeekHeader = this.cfg.getProperty(defCfg.SHOW_WEEK_HEADER.key); var mindate = this.cfg.getProperty(defCfg.MINDATE.key); var maxdate = this.cfg.getProperty(defCfg.MAXDATE.key); if (mindate) { mindate = YAHOO.widget.DateMath.clearTime(mindate); } if (maxdate) { maxdate = YAHOO.widget.DateMath.clearTime(maxdate); } html[html.length] = ''; var i = 0; var tempDiv = document.createElement("div"); var cell = document.createElement("td"); tempDiv.appendChild(cell); var jan1 = new Date(useDate.getFullYear(),0,1); var cal = this.parent || this; for (var r=0;r<6;r++) { weekNum = YAHOO.widget.DateMath.getWeekNumber(workingDate, useDate.getFullYear(), 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] = ''; if (showWeekHeader) { html = this.renderRowHeader(weekNum, html); } for (var d=0;d<7;d++){ // Render actual days cellRenderers = []; renderer = null; this.clearElement(cell); cell.className = this.Style.CSS_CELL; cell.id = this.id + cellPrefix + i; this.logger.log("Rendering cell " + cell.id + " (" + workingDate.getFullYear() + "-" + (workingDate.getMonth()+1) + "-" + workingDate.getDate() + ")", "cellrender"); 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 { YAHOO.util.Dom.addClass(cell, workingDayPrefix + workingDate.getDay()); YAHOO.util.Dom.addClass(cell, dayPrefix + workingDate.getDate()); for (var s=0;s= d1.getTime() && workingDate.getTime() <= d2.getTime()) { renderer = rArray[2]; if (workingDate.getTime()==d2.getTime()) { this.renderStack.splice(s,1); } } break; case YAHOO.widget.Calendar.WEEKDAY: var weekday = rArray[1][0]; if (workingDate.getDay()+1 == weekday) { renderer = rArray[2]; } break; case YAHOO.widget.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) { this.logger.log("renderer[" + x + "] for (" + workingDate.getFullYear() + "-" + (workingDate.getMonth()+1) + "-" + workingDate.getDate() + ")", "cellrender"); if (cellRenderers[x].call(cal, workingDate, cell) == YAHOO.widget.Calendar.STOP_RENDER) { break; } } workingDate.setTime(workingDate.getTime() + YAHOO.widget.DateMath.ONE_DAY_MS); if (i >= 0 && i <= 6) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_TOP); } if ((i % 7) === 0) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_LEFT); } if (((i+1) % 7) === 0) { YAHOO.util.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= ((this.preMonthDays+postDays+this.monthDays)-7)) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_BOTTOM); } html[html.length] = tempDiv.innerHTML; i++; } if (showWeekFooter) { html = this.renderRowFooter(weekNum, html); } html[html.length] = ''; } } html[html.length] = ''; 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 */ YAHOO.widget.Calendar.prototype.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 */ YAHOO.widget.Calendar.prototype.render = function() { this.beforeRenderEvent.fire(); var defCfg = YAHOO.widget.Calendar._DEFAULT_CONFIG; // Find starting day of the current month var workingDate = YAHOO.widget.DateMath.findMonthStart(this.cfg.getProperty(defCfg.PAGEDATE.key)); this.resetRenderers(); this.cellDates.length = 0; YAHOO.util.Event.purgeElement(this.oDomContainer, true); var html = []; html[html.length] = ''; html = this.renderHeader(html); html = this.renderBody(workingDate, html); html = this.renderFooter(html); html[html.length] = '
'; this.oDomContainer.innerHTML = html.join("\n"); this.applyListeners(); this.cells = this.oDomContainer.getElementsByTagName("td"); this.cfg.refireEvent(defCfg.TITLE.key); this.cfg.refireEvent(defCfg.CLOSE.key); this.cfg.refireEvent(defCfg.IFRAME.key); this.renderEvent.fire(); }; /** * Applies the Calendar's DOM listeners to applicable elements. * @method applyListeners */ YAHOO.widget.Calendar.prototype.applyListeners = function() { var root = this.oDomContainer; var cal = this.parent || this; var anchor = "a"; var mousedown = "mousedown"; var linkLeft = YAHOO.util.Dom.getElementsByClassName(this.Style.CSS_NAV_LEFT, anchor, root); var linkRight = YAHOO.util.Dom.getElementsByClassName(this.Style.CSS_NAV_RIGHT, anchor, root); if (linkLeft && linkLeft.length > 0) { this.linkLeft = linkLeft[0]; YAHOO.util.Event.addListener(this.linkLeft, mousedown, cal.previousMonth, cal, true); } if (linkRight && linkRight.length > 0) { this.linkRight = linkRight[0]; YAHOO.util.Event.addListener(this.linkRight, mousedown, cal.nextMonth, cal, true); } if (this.domEventMap) { var el,elements; for (var cls in this.domEventMap) { if (YAHOO.lang.hasOwnProperty(this.domEventMap, cls)) { var items = this.domEventMap[cls]; if (! (items instanceof Array)) { items = [items]; } for (var i=0;i'; 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 */ YAHOO.widget.Calendar.prototype.renderRowFooter = function(weekNum, html) { html[html.length] = '' + weekNum + ''; 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 */ YAHOO.widget.Calendar.prototype.renderCellDefault = function(workingDate, cell) { cell.innerHTML = '' + this.buildDayLabel(workingDate) + ""; }; /** * 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 */ YAHOO.widget.Calendar.prototype.styleCellDefault = function(workingDate, cell) { YAHOO.util.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 */ YAHOO.widget.Calendar.prototype.renderCellStyleHighlight1 = function(workingDate, cell) { YAHOO.util.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 */ YAHOO.widget.Calendar.prototype.renderCellStyleHighlight2 = function(workingDate, cell) { YAHOO.util.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 */ YAHOO.widget.Calendar.prototype.renderCellStyleHighlight3 = function(workingDate, cell) { YAHOO.util.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 */ YAHOO.widget.Calendar.prototype.renderCellStyleHighlight4 = function(workingDate, cell) { YAHOO.util.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 */ YAHOO.widget.Calendar.prototype.renderCellStyleToday = function(workingDate, cell) { YAHOO.util.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 */ YAHOO.widget.Calendar.prototype.renderCellStyleSelected = function(workingDate, cell) { YAHOO.util.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 */ YAHOO.widget.Calendar.prototype.renderCellNotThisMonth = function(workingDate, cell) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_OOM); cell.innerHTML=workingDate.getDate(); return YAHOO.widget.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 */ YAHOO.widget.Calendar.prototype.renderBodyCellRestricted = function(workingDate, cell) { YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL); YAHOO.util.Dom.addClass(cell, this.Style.CSS_CELL_RESTRICTED); cell.innerHTML=workingDate.getDate(); return YAHOO.widget.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 */ YAHOO.widget.Calendar.prototype.addMonths = function(count) { var cfgPageDate = YAHOO.widget.Calendar._DEFAULT_CONFIG.PAGEDATE.key; this.cfg.setProperty(cfgPageDate, YAHOO.widget.DateMath.add(this.cfg.getProperty(cfgPageDate), YAHOO.widget.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 */ YAHOO.widget.Calendar.prototype.subtractMonths = function(count) { var cfgPageDate = YAHOO.widget.Calendar._DEFAULT_CONFIG.PAGEDATE.key; this.cfg.setProperty(cfgPageDate, YAHOO.widget.DateMath.subtract(this.cfg.getProperty(cfgPageDate), YAHOO.widget.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 */ YAHOO.widget.Calendar.prototype.addYears = function(count) { var cfgPageDate = YAHOO.widget.Calendar._DEFAULT_CONFIG.PAGEDATE.key; this.cfg.setProperty(cfgPageDate, YAHOO.widget.DateMath.add(this.cfg.getProperty(cfgPageDate), YAHOO.widget.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 */ YAHOO.widget.Calendar.prototype.subtractYears = function(count) { var cfgPageDate = YAHOO.widget.Calendar._DEFAULT_CONFIG.PAGEDATE.key; this.cfg.setProperty(cfgPageDate, YAHOO.widget.DateMath.subtract(this.cfg.getProperty(cfgPageDate), YAHOO.widget.DateMath.YEAR, count)); this.resetRenderers(); this.changePageEvent.fire(); }; /** * Navigates to the next month page in the calendar widget. * @method nextMonth */ YAHOO.widget.Calendar.prototype.nextMonth = function() { this.addMonths(1); }; /** * Navigates to the previous month page in the calendar widget. * @method previousMonth */ YAHOO.widget.Calendar.prototype.previousMonth = function() { this.subtractMonths(1); }; /** * Navigates to the next year in the currently selected month in the calendar widget. * @method nextYear */ YAHOO.widget.Calendar.prototype.nextYear = function() { this.addYears(1); }; /** * Navigates to the previous year in the currently selected month in the calendar widget. * @method previousYear */ YAHOO.widget.Calendar.prototype.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 */ YAHOO.widget.Calendar.prototype.reset = function() { var defCfg = YAHOO.widget.Calendar._DEFAULT_CONFIG; this.cfg.resetProperty(defCfg.SELECTED.key); this.cfg.resetProperty(defCfg.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 */ YAHOO.widget.Calendar.prototype.clear = function() { var defCfg = YAHOO.widget.Calendar._DEFAULT_CONFIG; this.cfg.setProperty(defCfg.SELECTED.key, []); this.cfg.setProperty(defCfg.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. */ YAHOO.widget.Calendar.prototype.select = function(date) { this.logger.log("Select: " + date, "info"); var aToBeSelected = this._toFieldArray(date); this.logger.log("Selection field array: " + aToBeSelected, "info"); // Filtered array of valid dates var validDates = []; var selected = []; var cfgSelected = YAHOO.widget.Calendar._DEFAULT_CONFIG.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) { this.logger.log("All provided dates were OOB. beforeSelect and select events not fired", "info"); } 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. */ YAHOO.widget.Calendar.prototype.selectCell = function(cellIndex) { var cell = this.cells[cellIndex]; var cellDate = this.cellDates[cellIndex]; var dCellDate = this._toDate(cellDate); this.logger.log("Select: " + dCellDate, "info"); var selectable = YAHOO.util.Dom.hasClass(cell, this.Style.CSS_CELL_SELECTABLE); if (!selectable) {this.logger.log("The cell at cellIndex:" + cellIndex + " is not a selectable cell. beforeSelect, select events not fired", "info"); } if (selectable) { this.beforeSelectEvent.fire(); var cfgSelected = YAHOO.widget.Calendar._DEFAULT_CONFIG.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. */ YAHOO.widget.Calendar.prototype.deselect = function(date) { this.logger.log("Deselect: " + date, "info"); var aToBeDeselected = this._toFieldArray(date); this.logger.log("Deselection field array: " + aToBeDeselected, "info"); var validDates = []; var selected = []; var cfgSelected = YAHOO.widget.Calendar._DEFAULT_CONFIG.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) { this.logger.log("All provided dates were OOB. beforeDeselect and deselect events not fired");} 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. */ YAHOO.widget.Calendar.prototype.deselectCell = function(cellIndex) { var cell = this.cells[cellIndex]; var cellDate = this.cellDates[cellIndex]; var cellDateIndex = this._indexOfSelectedFieldArray(cellDate); var selectable = YAHOO.util.Dom.hasClass(cell, this.Style.CSS_CELL_SELECTABLE); if (!selectable) { this.logger.log("The cell at cellIndex:" + cellIndex + " is not a selectable/deselectable cell", "info"); } if (selectable) { this.beforeDeselectEvent.fire(); var defCfg = YAHOO.widget.Calendar._DEFAULT_CONFIG; var selected = this.cfg.getProperty(defCfg.SELECTED.key); var dCellDate = this._toDate(cellDate); var selectDate = cellDate.concat(); if (cellDateIndex > -1) { if (this.cfg.getProperty(defCfg.PAGEDATE.key).getMonth() == dCellDate.getMonth() && this.cfg.getProperty(defCfg.PAGEDATE.key).getFullYear() == dCellDate.getFullYear()) { YAHOO.util.Dom.removeClass(cell, this.Style.CSS_CELL_SELECTED); } selected.splice(cellDateIndex, 1); } if (this.parent) { this.parent.cfg.setProperty(defCfg.SELECTED.key, selected); } else { this.cfg.setProperty(defCfg.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. */ YAHOO.widget.Calendar.prototype.deselectAll = function() { this.beforeDeselectEvent.fire(); var cfgSelected = YAHOO.widget.Calendar._DEFAULT_CONFIG.SELECTED.key; var selected = this.cfg.getProperty(cfgSelected); var count = selected.length; var 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 */ YAHOO.widget.Calendar.prototype._toFieldArray = function(date) { var returnDate = []; if (date instanceof Date) { returnDate = [[date.getFullYear(), date.getMonth()+1, date.getDate()]]; } else if (YAHOO.lang.isString(date)) { returnDate = this._parseDates(date); } else if (YAHOO.lang.isArray(date)) { for (var i=0;i 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 */ YAHOO.widget.Calendar.prototype._parsePageDate = function(date) { var parsedDate; var defCfg = YAHOO.widget.Calendar._DEFAULT_CONFIG; if (date) { if (date instanceof Date) { parsedDate = YAHOO.widget.DateMath.findMonthStart(date); } else { var month, year, aMonthYear; aMonthYear = date.split(this.cfg.getProperty(defCfg.DATE_FIELD_DELIMITER.key)); month = parseInt(aMonthYear[this.cfg.getProperty(defCfg.MY_MONTH_POSITION.key)-1], 10)-1; year = parseInt(aMonthYear[this.cfg.getProperty(defCfg.MY_YEAR_POSITION.key)-1], 10); parsedDate = new Date(year, month, 1); } } else { parsedDate = new Date(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. */ YAHOO.widget.Calendar.prototype.onBeforeSelect = function() { if (this.cfg.getProperty(YAHOO.widget.Calendar._DEFAULT_CONFIG.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. */ YAHOO.widget.Calendar.prototype.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. */ YAHOO.widget.Calendar.prototype.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. */ YAHOO.widget.Calendar.prototype.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. */ YAHOO.widget.Calendar.prototype.onChangePage = function() { this.render(); }; /** * Event executed when the calendar widget is rendered. * @deprecated Event handlers for this event should be susbcribed to renderEvent. */ YAHOO.widget.Calendar.prototype.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. */ YAHOO.widget.Calendar.prototype.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. */ YAHOO.widget.Calendar.prototype.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 */ YAHOO.widget.Calendar.prototype.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[]) */ YAHOO.widget.Calendar.prototype._parseDate = function(sDate) { var aDate = sDate.split(this.Locale.DATE_FIELD_DELIMITER); var rArray; if (aDate.length == 2) { rArray = [aDate[this.Locale.MD_MONTH_POSITION-1],aDate[this.Locale.MD_DAY_POSITION-1]]; rArray.type = YAHOO.widget.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 = YAHOO.widget.Calendar.DATE; } for (var i=0;i *
*
* * The tables for the calendars ("cal1_0" and "cal1_1") will be inserted into those containers. * @namespace YAHOO.widget * @class CalendarGroup * @constructor * @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 */ YAHOO.widget.CalendarGroup = function(id, containerId, config) { if (arguments.length > 0) { this.init(id, containerId, config); } }; /** * Initializes the calendar group. All subclasses must call this method in order for the * group to be initialized properly. * @method init * @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 */ YAHOO.widget.CalendarGroup.prototype.init = function(id, containerId, config) { this.logger = new YAHOO.widget.LogWriter("CalendarGroup " + id); this.initEvents(); this.initStyles(); /** * The collection of Calendar pages contained within the CalendarGroup * @property pages * @type YAHOO.widget.Calendar[] */ this.pages = []; /** * 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 = containerId; /** * The outer containing element for the CalendarGroup * @property oDomContainer * @type HTMLElement */ this.oDomContainer = document.getElementById(containerId); YAHOO.util.Dom.addClass(this.oDomContainer, YAHOO.widget.CalendarGroup.CSS_CONTAINER); YAHOO.util.Dom.addClass(this.oDomContainer, YAHOO.widget.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.logger.log("Initialized " + this.pages.length + "-page CalendarGroup", "info"); }; YAHOO.widget.CalendarGroup.prototype.setupConfig = function() { var defCfg = YAHOO.widget.CalendarGroup._DEFAULT_CONFIG; /** * 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 */ this.cfg.addProperty(defCfg.PAGES.key, { value:defCfg.PAGES.value, validator:this.cfg.checkNumber, handler:this.configPages } ); /** * The month/year representing the current visible Calendar date (mm/yyyy) * @config pagedate * @type String * @default today's date */ this.cfg.addProperty(defCfg.PAGEDATE.key, { value:new Date(), handler:this.configPageDate } ); /** * The date or range of dates representing the current Calendar selection * @config selected * @type String * @default [] */ this.cfg.addProperty(defCfg.SELECTED.key, { value:[], handler:this.configSelected } ); /** * The title to display above the CalendarGroup's month header * @config title * @type String * @default "" */ this.cfg.addProperty(defCfg.TITLE.key, { value:defCfg.TITLE.value, handler:this.configTitle } ); /** * Whether or not a close button should be displayed for this CalendarGroup * @config close * @type Boolean * @default false */ this.cfg.addProperty(defCfg.CLOSE.key, { value:defCfg.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 */ this.cfg.addProperty(defCfg.IFRAME.key, { value:defCfg.IFRAME.value, handler:this.configIframe, validator:this.cfg.checkBoolean } ); /** * The minimum selectable date in the current Calendar (mm/dd/yyyy) * @config mindate * @type String * @default null */ this.cfg.addProperty(defCfg.MINDATE.key, { value:defCfg.MINDATE.value, handler:this.delegateConfig } ); /** * The maximum selectable date in the current Calendar (mm/dd/yyyy) * @config maxdate * @type String * @default null */ this.cfg.addProperty(defCfg.MAXDATE.key, { value:defCfg.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 */ this.cfg.addProperty(defCfg.MULTI_SELECT.key, { value:defCfg.MULTI_SELECT.value, handler:this.delegateConfig, validator:this.cfg.checkBoolean } ); /** * The weekday the week begins on. Default is 0 (Sunday). * @config START_WEEKDAY * @type number * @default 0 */ this.cfg.addProperty(defCfg.START_WEEKDAY.key, { value:defCfg.START_WEEKDAY.value, handler:this.delegateConfig, validator:this.cfg.checkNumber } ); /** * True if the Calendar should show weekday labels. True by default. * @config SHOW_WEEKDAYS * @type Boolean * @default true */ this.cfg.addProperty(defCfg.SHOW_WEEKDAYS.key, { value:defCfg.SHOW_WEEKDAYS.value, handler:this.delegateConfig, validator:this.cfg.checkBoolean } ); /** * True if the Calendar should show week row headers. False by default. * @config SHOW_WEEK_HEADER * @type Boolean * @default false */ this.cfg.addProperty(defCfg.SHOW_WEEK_HEADER.key,{ value:defCfg.SHOW_WEEK_HEADER.value, handler:this.delegateConfig, validator:this.cfg.checkBoolean } ); /** * True if the Calendar should show week row footers. False by default. * @config SHOW_WEEK_FOOTER * @type Boolean * @default false */ this.cfg.addProperty(defCfg.SHOW_WEEK_FOOTER.key,{ value:defCfg.SHOW_WEEK_FOOTER.value, handler:this.delegateConfig, validator:this.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 */ this.cfg.addProperty(defCfg.HIDE_BLANK_WEEKS.key,{ value:defCfg.HIDE_BLANK_WEEKS.value, handler:this.delegateConfig, validator:this.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 */ this.cfg.addProperty(defCfg.NAV_ARROW_LEFT.key, { value:defCfg.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 */ this.cfg.addProperty(defCfg.NAV_ARROW_RIGHT.key, { value:defCfg.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"] */ this.cfg.addProperty(defCfg.MONTHS_SHORT.key, { value:defCfg.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" */ this.cfg.addProperty(defCfg.MONTHS_LONG.key, { value:defCfg.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"] */ this.cfg.addProperty(defCfg.WEEKDAYS_1CHAR.key, { value:defCfg.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"] */ this.cfg.addProperty(defCfg.WEEKDAYS_SHORT.key, { value:defCfg.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"] */ this.cfg.addProperty(defCfg.WEEKDAYS_MEDIUM.key, { value:defCfg.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"] */ this.cfg.addProperty(defCfg.WEEKDAYS_LONG.key, { value:defCfg.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" */ this.cfg.addProperty(defCfg.LOCALE_MONTHS.key, { value:defCfg.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" */ this.cfg.addProperty(defCfg.LOCALE_WEEKDAYS.key, { value:defCfg.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 "," */ this.cfg.addProperty(defCfg.DATE_DELIMITER.key, { value:defCfg.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 "/" */ this.cfg.addProperty(defCfg.DATE_FIELD_DELIMITER.key,{ value:defCfg.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 "-" */ this.cfg.addProperty(defCfg.DATE_RANGE_DELIMITER.key,{ value:defCfg.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 */ this.cfg.addProperty(defCfg.MY_MONTH_POSITION.key, { value:defCfg.MY_MONTH_POSITION.value, handler:this.delegateConfig, validator:this.cfg.checkNumber } ); /** * The position of the year in a month/year date string * @config MY_YEAR_POSITION * @type Number * @default 2 */ this.cfg.addProperty(defCfg.MY_YEAR_POSITION.key, { value:defCfg.MY_YEAR_POSITION.value, handler:this.delegateConfig, validator:this.cfg.checkNumber } ); /** * The position of the month in a month/day date string * @config MD_MONTH_POSITION * @type Number * @default 1 */ this.cfg.addProperty(defCfg.MD_MONTH_POSITION.key, { value:defCfg.MD_MONTH_POSITION.value, handler:this.delegateConfig, validator:this.cfg.checkNumber } ); /** * The position of the day in a month/year date string * @config MD_DAY_POSITION * @type Number * @default 2 */ this.cfg.addProperty(defCfg.MD_DAY_POSITION.key, { value:defCfg.MD_DAY_POSITION.value, handler:this.delegateConfig, validator:this.cfg.checkNumber } ); /** * The position of the month in a month/day/year date string * @config MDY_MONTH_POSITION * @type Number * @default 1 */ this.cfg.addProperty(defCfg.MDY_MONTH_POSITION.key, { value:defCfg.MDY_MONTH_POSITION.value, handler:this.delegateConfig, validator:this.cfg.checkNumber } ); /** * The position of the day in a month/day/year date string * @config MDY_DAY_POSITION * @type Number * @default 2 */ this.cfg.addProperty(defCfg.MDY_DAY_POSITION.key, { value:defCfg.MDY_DAY_POSITION.value, handler:this.delegateConfig, validator:this.cfg.checkNumber } ); /** * The position of the year in a month/day/year date string * @config MDY_YEAR_POSITION * @type Number * @default 3 */ this.cfg.addProperty(defCfg.MDY_YEAR_POSITION.key, { value:defCfg.MDY_YEAR_POSITION.value, handler:this.delegateConfig, validator:this.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 */ this.cfg.addProperty(defCfg.MY_LABEL_MONTH_POSITION.key, { value:defCfg.MY_LABEL_MONTH_POSITION.value, handler:this.delegateConfig, validator:this.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 */ this.cfg.addProperty(defCfg.MY_LABEL_YEAR_POSITION.key, { value:defCfg.MY_LABEL_YEAR_POSITION.value, handler:this.delegateConfig, validator:this.cfg.checkNumber } ); /** * The suffix used after the month when rendering the Calendar header * @config MY_LABEL_MONTH_SUFFIX * @type String * @default " " */ this.cfg.addProperty(defCfg.MY_LABEL_MONTH_SUFFIX.key, { value:defCfg.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 "" */ this.cfg.addProperty(defCfg.MY_LABEL_YEAR_SUFFIX.key, { value:defCfg.MY_LABEL_YEAR_SUFFIX.value, handler:this.delegateConfig } ); }; /** * Initializes CalendarGroup's built-in CustomEvents * @method initEvents */ YAHOO.widget.CalendarGroup.prototype.initEvents = function() { var me = this; var strEvent = "Event"; /** * 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 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. */ YAHOO.widget.CalendarGroup.prototype.delegateConfig = function(type, args, obj) { var val = args[0]; var cal; for (var p=0;p0) { year+=1; } cal.setYear(year); } }; /** * Calls the render function of all child calendars within the group. * @method render */ YAHOO.widget.CalendarGroup.prototype.render = function() { this.renderHeader(); for (var p=0;p *
  • If MULTI_SELECT is false, selectCell will select the cell at the specified index for only the last displayed Calendar page.
  • *
  • If MULTI_SELECT is true, selectCell will select the cell at the specified index, on each displayed Calendar page.
  • * * @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. */ YAHOO.widget.CalendarGroup.prototype.selectCell = function(cellIndex) { for (var p=0;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 */ YAHOO.widget.CalendarGroup.prototype.nextYear = function() { for (var p=0;p 11)) { var DM = YAHOO.widget.DateMath; var newDate = DM.add(date, DM.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 */ YAHOO.widget.CalendarGroup.prototype._fixWidth = function() { var startW = this.oDomContainer.offsetWidth; var w = 0; for (var p=0;p 0) { this.oDomContainer.style.width = w + "px"; } }; /** * CSS class representing the container for the calendar * @property YAHOO.widget.CalendarGroup.CSS_CONTAINER * @static * @final * @type String */ YAHOO.widget.CalendarGroup.CSS_CONTAINER = "yui-calcontainer"; /** * CSS class representing the container for the calendar * @property YAHOO.widget.CalendarGroup.CSS_MULTI_UP * @static * @final * @type String */ YAHOO.widget.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 */ YAHOO.widget.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 Style.CSS_CLOSE property now represents the CSS class used to render the close icon * @type String */ YAHOO.widget.CalendarGroup.CSS_2UPCLOSE = "close-icon"; YAHOO.lang.augmentProto(YAHOO.widget.CalendarGroup, YAHOO.widget.Calendar, "buildDayLabel", "buildMonthLabel", "renderOutOfBoundsDate", "renderRowHeader", "renderRowFooter", "renderCellDefault", "styleCellDefault", "renderCellStyleHighlight1", "renderCellStyleHighlight2", "renderCellStyleHighlight3", "renderCellStyleHighlight4", "renderCellStyleToday", "renderCellStyleSelected", "renderCellNotThisMonth", "renderBodyCellRestricted", "initStyles", "configTitle", "configClose", "configIframe", "hide", "browser"); /** * The set of default Config property keys and values for the CalendarGroup * @property YAHOO.widget.CalendarGroup._DEFAULT_CONFIG * @final * @static * @private * @type Object */ YAHOO.widget.CalendarGroup._DEFAULT_CONFIG = YAHOO.widget.Calendar._DEFAULT_CONFIG; YAHOO.widget.CalendarGroup._DEFAULT_CONFIG.PAGES = {key:"pages", value:2}; /** * Returns a string representation of the object. * @method toString * @return {String} A string representation of the CalendarGroup object. */ YAHOO.widget.CalendarGroup.prototype.toString = function() { return "CalendarGroup " + this.id; }; YAHOO.widget.CalGrp = YAHOO.widget.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, YAHOO.widget.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; YAHOO.register("calendar", YAHOO.widget.Calendar, {version: "2.3.0", build: "442"});