PageRenderTime 78ms CodeModel.GetById 21ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 2ms

/src/main/resources/org/apache/struts2/static/calendar/calendar.js

http://struts2yuiplugin.googlecode.com/
JavaScript | 7148 lines | 3010 code | 916 blank | 3222 comment | 553 complexity | c1f4fbc5d520aed1d29fc19fd4378d7a MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2Copyright (c) 2009, Yahoo! Inc. All rights reserved.
   3Code licensed under the BSD License:
   4http://developer.yahoo.net/yui/license.txt
   5version: 2.7.0
   6*/
   7(function () {
   8
   9    /**
  10    * Config is a utility used within an Object to allow the implementer to
  11    * maintain a list of local configuration properties and listen for changes 
  12    * to those properties dynamically using CustomEvent. The initial values are 
  13    * also maintained so that the configuration can be reset at any given point 
  14    * to its initial state.
  15    * @namespace YAHOO.util
  16    * @class Config
  17    * @constructor
  18    * @param {Object} owner The owner Object to which this Config Object belongs
  19    */
  20    YAHOO.util.Config = function (owner) {
  21
  22        if (owner) {
  23            this.init(owner);
  24        }
  25
  26
  27    };
  28
  29
  30    var Lang = YAHOO.lang,
  31        CustomEvent = YAHOO.util.CustomEvent,
  32        Config = YAHOO.util.Config;
  33
  34
  35    /**
  36     * Constant representing the CustomEvent type for the config changed event.
  37     * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
  38     * @private
  39     * @static
  40     * @final
  41     */
  42    Config.CONFIG_CHANGED_EVENT = "configChanged";
  43    
  44    /**
  45     * Constant representing the boolean type string
  46     * @property YAHOO.util.Config.BOOLEAN_TYPE
  47     * @private
  48     * @static
  49     * @final
  50     */
  51    Config.BOOLEAN_TYPE = "boolean";
  52    
  53    Config.prototype = {
  54     
  55        /**
  56        * Object reference to the owner of this Config Object
  57        * @property owner
  58        * @type Object
  59        */
  60        owner: null,
  61        
  62        /**
  63        * Boolean flag that specifies whether a queue is currently 
  64        * being executed
  65        * @property queueInProgress
  66        * @type Boolean
  67        */
  68        queueInProgress: false,
  69        
  70        /**
  71        * Maintains the local collection of configuration property objects and 
  72        * their specified values
  73        * @property config
  74        * @private
  75        * @type Object
  76        */ 
  77        config: null,
  78        
  79        /**
  80        * Maintains the local collection of configuration property objects as 
  81        * they were initially applied.
  82        * This object is used when resetting a property.
  83        * @property initialConfig
  84        * @private
  85        * @type Object
  86        */ 
  87        initialConfig: null,
  88        
  89        /**
  90        * Maintains the local, normalized CustomEvent queue
  91        * @property eventQueue
  92        * @private
  93        * @type Object
  94        */ 
  95        eventQueue: null,
  96        
  97        /**
  98        * Custom Event, notifying subscribers when Config properties are set 
  99        * (setProperty is called without the silent flag
 100        * @event configChangedEvent
 101        */
 102        configChangedEvent: null,
 103    
 104        /**
 105        * Initializes the configuration Object and all of its local members.
 106        * @method init
 107        * @param {Object} owner The owner Object to which this Config 
 108        * Object belongs
 109        */
 110        init: function (owner) {
 111    
 112            this.owner = owner;
 113    
 114            this.configChangedEvent = 
 115                this.createEvent(Config.CONFIG_CHANGED_EVENT);
 116    
 117            this.configChangedEvent.signature = CustomEvent.LIST;
 118            this.queueInProgress = false;
 119            this.config = {};
 120            this.initialConfig = {};
 121            this.eventQueue = [];
 122        
 123        },
 124        
 125        /**
 126        * Validates that the value passed in is a Boolean.
 127        * @method checkBoolean
 128        * @param {Object} val The value to validate
 129        * @return {Boolean} true, if the value is valid
 130        */ 
 131        checkBoolean: function (val) {
 132            return (typeof val == Config.BOOLEAN_TYPE);
 133        },
 134        
 135        /**
 136        * Validates that the value passed in is a number.
 137        * @method checkNumber
 138        * @param {Object} val The value to validate
 139        * @return {Boolean} true, if the value is valid
 140        */
 141        checkNumber: function (val) {
 142            return (!isNaN(val));
 143        },
 144        
 145        /**
 146        * Fires a configuration property event using the specified value. 
 147        * @method fireEvent
 148        * @private
 149        * @param {String} key The configuration property's name
 150        * @param {value} Object The value of the correct type for the property
 151        */ 
 152        fireEvent: function ( key, value ) {
 153            var property = this.config[key];
 154        
 155            if (property && property.event) {
 156                property.event.fire(value);
 157            } 
 158        },
 159        
 160        /**
 161        * Adds a property to the Config Object's private config hash.
 162        * @method addProperty
 163        * @param {String} key The configuration property's name
 164        * @param {Object} propertyObject The Object containing all of this 
 165        * property's arguments
 166        */
 167        addProperty: function ( key, propertyObject ) {
 168            key = key.toLowerCase();
 169        
 170            this.config[key] = propertyObject;
 171        
 172            propertyObject.event = this.createEvent(key, { scope: this.owner });
 173            propertyObject.event.signature = CustomEvent.LIST;
 174            
 175            
 176            propertyObject.key = key;
 177        
 178            if (propertyObject.handler) {
 179                propertyObject.event.subscribe(propertyObject.handler, 
 180                    this.owner);
 181            }
 182        
 183            this.setProperty(key, propertyObject.value, true);
 184            
 185            if (! propertyObject.suppressEvent) {
 186                this.queueProperty(key, propertyObject.value);
 187            }
 188            
 189        },
 190        
 191        /**
 192        * Returns a key-value configuration map of the values currently set in  
 193        * the Config Object.
 194        * @method getConfig
 195        * @return {Object} The current config, represented in a key-value map
 196        */
 197        getConfig: function () {
 198        
 199            var cfg = {},
 200                currCfg = this.config,
 201                prop,
 202                property;
 203                
 204            for (prop in currCfg) {
 205                if (Lang.hasOwnProperty(currCfg, prop)) {
 206                    property = currCfg[prop];
 207                    if (property && property.event) {
 208                        cfg[prop] = property.value;
 209                    }
 210                }
 211            }
 212
 213            return cfg;
 214        },
 215        
 216        /**
 217        * Returns the value of specified property.
 218        * @method getProperty
 219        * @param {String} key The name of the property
 220        * @return {Object}  The value of the specified property
 221        */
 222        getProperty: function (key) {
 223            var property = this.config[key.toLowerCase()];
 224            if (property && property.event) {
 225                return property.value;
 226            } else {
 227                return undefined;
 228            }
 229        },
 230        
 231        /**
 232        * Resets the specified property's value to its initial value.
 233        * @method resetProperty
 234        * @param {String} key The name of the property
 235        * @return {Boolean} True is the property was reset, false if not
 236        */
 237        resetProperty: function (key) {
 238    
 239            key = key.toLowerCase();
 240        
 241            var property = this.config[key];
 242    
 243            if (property && property.event) {
 244    
 245                if (this.initialConfig[key] && 
 246                    !Lang.isUndefined(this.initialConfig[key])) {
 247    
 248                    this.setProperty(key, this.initialConfig[key]);
 249
 250                    return true;
 251    
 252                }
 253    
 254            } else {
 255    
 256                return false;
 257            }
 258    
 259        },
 260        
 261        /**
 262        * Sets the value of a property. If the silent property is passed as 
 263        * true, the property's event will not be fired.
 264        * @method setProperty
 265        * @param {String} key The name of the property
 266        * @param {String} value The value to set the property to
 267        * @param {Boolean} silent Whether the value should be set silently, 
 268        * without firing the property event.
 269        * @return {Boolean} True, if the set was successful, false if it failed.
 270        */
 271        setProperty: function (key, value, silent) {
 272        
 273            var property;
 274        
 275            key = key.toLowerCase();
 276        
 277            if (this.queueInProgress && ! silent) {
 278                // Currently running through a queue... 
 279                this.queueProperty(key,value);
 280                return true;
 281    
 282            } else {
 283                property = this.config[key];
 284                if (property && property.event) {
 285                    if (property.validator && !property.validator(value)) {
 286                        return false;
 287                    } else {
 288                        property.value = value;
 289                        if (! silent) {
 290                            this.fireEvent(key, value);
 291                            this.configChangedEvent.fire([key, value]);
 292                        }
 293                        return true;
 294                    }
 295                } else {
 296                    return false;
 297                }
 298            }
 299        },
 300        
 301        /**
 302        * Sets the value of a property and queues its event to execute. If the 
 303        * event is already scheduled to execute, it is
 304        * moved from its current position to the end of the queue.
 305        * @method queueProperty
 306        * @param {String} key The name of the property
 307        * @param {String} value The value to set the property to
 308        * @return {Boolean}  true, if the set was successful, false if 
 309        * it failed.
 310        */ 
 311        queueProperty: function (key, value) {
 312        
 313            key = key.toLowerCase();
 314        
 315            var property = this.config[key],
 316                foundDuplicate = false,
 317                iLen,
 318                queueItem,
 319                queueItemKey,
 320                queueItemValue,
 321                sLen,
 322                supercedesCheck,
 323                qLen,
 324                queueItemCheck,
 325                queueItemCheckKey,
 326                queueItemCheckValue,
 327                i,
 328                s,
 329                q;
 330                                
 331            if (property && property.event) {
 332    
 333                if (!Lang.isUndefined(value) && property.validator && 
 334                    !property.validator(value)) { // validator
 335                    return false;
 336                } else {
 337        
 338                    if (!Lang.isUndefined(value)) {
 339                        property.value = value;
 340                    } else {
 341                        value = property.value;
 342                    }
 343        
 344                    foundDuplicate = false;
 345                    iLen = this.eventQueue.length;
 346        
 347                    for (i = 0; i < iLen; i++) {
 348                        queueItem = this.eventQueue[i];
 349        
 350                        if (queueItem) {
 351                            queueItemKey = queueItem[0];
 352                            queueItemValue = queueItem[1];
 353
 354                            if (queueItemKey == key) {
 355    
 356                                /*
 357                                    found a dupe... push to end of queue, null 
 358                                    current item, and break
 359                                */
 360    
 361                                this.eventQueue[i] = null;
 362    
 363                                this.eventQueue.push(
 364                                    [key, (!Lang.isUndefined(value) ? 
 365                                    value : queueItemValue)]);
 366    
 367                                foundDuplicate = true;
 368                                break;
 369                            }
 370                        }
 371                    }
 372                    
 373                    // this is a refire, or a new property in the queue
 374    
 375                    if (! foundDuplicate && !Lang.isUndefined(value)) { 
 376                        this.eventQueue.push([key, value]);
 377                    }
 378                }
 379        
 380                if (property.supercedes) {
 381
 382                    sLen = property.supercedes.length;
 383
 384                    for (s = 0; s < sLen; s++) {
 385
 386                        supercedesCheck = property.supercedes[s];
 387                        qLen = this.eventQueue.length;
 388
 389                        for (q = 0; q < qLen; q++) {
 390                            queueItemCheck = this.eventQueue[q];
 391
 392                            if (queueItemCheck) {
 393                                queueItemCheckKey = queueItemCheck[0];
 394                                queueItemCheckValue = queueItemCheck[1];
 395
 396                                if (queueItemCheckKey == 
 397                                    supercedesCheck.toLowerCase() ) {
 398
 399                                    this.eventQueue.push([queueItemCheckKey, 
 400                                        queueItemCheckValue]);
 401
 402                                    this.eventQueue[q] = null;
 403                                    break;
 404
 405                                }
 406                            }
 407                        }
 408                    }
 409                }
 410
 411
 412                return true;
 413            } else {
 414                return false;
 415            }
 416        },
 417        
 418        /**
 419        * Fires the event for a property using the property's current value.
 420        * @method refireEvent
 421        * @param {String} key The name of the property
 422        */
 423        refireEvent: function (key) {
 424    
 425            key = key.toLowerCase();
 426        
 427            var property = this.config[key];
 428    
 429            if (property && property.event && 
 430    
 431                !Lang.isUndefined(property.value)) {
 432    
 433                if (this.queueInProgress) {
 434    
 435                    this.queueProperty(key);
 436    
 437                } else {
 438    
 439                    this.fireEvent(key, property.value);
 440    
 441                }
 442    
 443            }
 444        },
 445        
 446        /**
 447        * Applies a key-value Object literal to the configuration, replacing  
 448        * any existing values, and queueing the property events.
 449        * Although the values will be set, fireQueue() must be called for their 
 450        * associated events to execute.
 451        * @method applyConfig
 452        * @param {Object} userConfig The configuration Object literal
 453        * @param {Boolean} init  When set to true, the initialConfig will 
 454        * be set to the userConfig passed in, so that calling a reset will 
 455        * reset the properties to the passed values.
 456        */
 457        applyConfig: function (userConfig, init) {
 458        
 459            var sKey,
 460                oConfig;
 461
 462            if (init) {
 463                oConfig = {};
 464                for (sKey in userConfig) {
 465                    if (Lang.hasOwnProperty(userConfig, sKey)) {
 466                        oConfig[sKey.toLowerCase()] = userConfig[sKey];
 467                    }
 468                }
 469                this.initialConfig = oConfig;
 470            }
 471
 472            for (sKey in userConfig) {
 473                if (Lang.hasOwnProperty(userConfig, sKey)) {
 474                    this.queueProperty(sKey, userConfig[sKey]);
 475                }
 476            }
 477        },
 478        
 479        /**
 480        * Refires the events for all configuration properties using their 
 481        * current values.
 482        * @method refresh
 483        */
 484        refresh: function () {
 485
 486            var prop;
 487
 488            for (prop in this.config) {
 489                if (Lang.hasOwnProperty(this.config, prop)) {
 490                    this.refireEvent(prop);
 491                }
 492            }
 493        },
 494        
 495        /**
 496        * Fires the normalized list of queued property change events
 497        * @method fireQueue
 498        */
 499        fireQueue: function () {
 500        
 501            var i, 
 502                queueItem,
 503                key,
 504                value,
 505                property;
 506        
 507            this.queueInProgress = true;
 508            for (i = 0;i < this.eventQueue.length; i++) {
 509                queueItem = this.eventQueue[i];
 510                if (queueItem) {
 511        
 512                    key = queueItem[0];
 513                    value = queueItem[1];
 514                    property = this.config[key];
 515
 516                    property.value = value;
 517
 518                    // Clear out queue entry, to avoid it being 
 519                    // re-added to the queue by any queueProperty/supercedes
 520                    // calls which are invoked during fireEvent
 521                    this.eventQueue[i] = null;
 522
 523                    this.fireEvent(key,value);
 524                }
 525            }
 526            
 527            this.queueInProgress = false;
 528            this.eventQueue = [];
 529        },
 530        
 531        /**
 532        * Subscribes an external handler to the change event for any 
 533        * given property. 
 534        * @method subscribeToConfigEvent
 535        * @param {String} key The property name
 536        * @param {Function} handler The handler function to use subscribe to 
 537        * the property's event
 538        * @param {Object} obj The Object to use for scoping the event handler 
 539        * (see CustomEvent documentation)
 540        * @param {Boolean} override Optional. If true, will override "this"  
 541        * within the handler to map to the scope Object passed into the method.
 542        * @return {Boolean} True, if the subscription was successful, 
 543        * otherwise false.
 544        */ 
 545        subscribeToConfigEvent: function (key, handler, obj, override) {
 546    
 547            var property = this.config[key.toLowerCase()];
 548    
 549            if (property && property.event) {
 550                if (!Config.alreadySubscribed(property.event, handler, obj)) {
 551                    property.event.subscribe(handler, obj, override);
 552                }
 553                return true;
 554            } else {
 555                return false;
 556            }
 557    
 558        },
 559        
 560        /**
 561        * Unsubscribes an external handler from the change event for any 
 562        * given property. 
 563        * @method unsubscribeFromConfigEvent
 564        * @param {String} key The property name
 565        * @param {Function} handler The handler function to use subscribe to 
 566        * the property's event
 567        * @param {Object} obj The Object to use for scoping the event 
 568        * handler (see CustomEvent documentation)
 569        * @return {Boolean} True, if the unsubscription was successful, 
 570        * otherwise false.
 571        */
 572        unsubscribeFromConfigEvent: function (key, handler, obj) {
 573            var property = this.config[key.toLowerCase()];
 574            if (property && property.event) {
 575                return property.event.unsubscribe(handler, obj);
 576            } else {
 577                return false;
 578            }
 579        },
 580        
 581        /**
 582        * Returns a string representation of the Config object
 583        * @method toString
 584        * @return {String} The Config object in string format.
 585        */
 586        toString: function () {
 587            var output = "Config";
 588            if (this.owner) {
 589                output += " [" + this.owner.toString() + "]";
 590            }
 591            return output;
 592        },
 593        
 594        /**
 595        * Returns a string representation of the Config object's current 
 596        * CustomEvent queue
 597        * @method outputEventQueue
 598        * @return {String} The string list of CustomEvents currently queued 
 599        * for execution
 600        */
 601        outputEventQueue: function () {
 602
 603            var output = "",
 604                queueItem,
 605                q,
 606                nQueue = this.eventQueue.length;
 607              
 608            for (q = 0; q < nQueue; q++) {
 609                queueItem = this.eventQueue[q];
 610                if (queueItem) {
 611                    output += queueItem[0] + "=" + queueItem[1] + ", ";
 612                }
 613            }
 614            return output;
 615        },
 616
 617        /**
 618        * Sets all properties to null, unsubscribes all listeners from each 
 619        * property's change event and all listeners from the configChangedEvent.
 620        * @method destroy
 621        */
 622        destroy: function () {
 623
 624            var oConfig = this.config,
 625                sProperty,
 626                oProperty;
 627
 628
 629            for (sProperty in oConfig) {
 630            
 631                if (Lang.hasOwnProperty(oConfig, sProperty)) {
 632
 633                    oProperty = oConfig[sProperty];
 634
 635                    oProperty.event.unsubscribeAll();
 636                    oProperty.event = null;
 637
 638                }
 639            
 640            }
 641            
 642            this.configChangedEvent.unsubscribeAll();
 643            
 644            this.configChangedEvent = null;
 645            this.owner = null;
 646            this.config = null;
 647            this.initialConfig = null;
 648            this.eventQueue = null;
 649        
 650        }
 651
 652    };
 653    
 654    
 655    
 656    /**
 657    * Checks to determine if a particular function/Object pair are already 
 658    * subscribed to the specified CustomEvent
 659    * @method YAHOO.util.Config.alreadySubscribed
 660    * @static
 661    * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check 
 662    * the subscriptions
 663    * @param {Function} fn The function to look for in the subscribers list
 664    * @param {Object} obj The execution scope Object for the subscription
 665    * @return {Boolean} true, if the function/Object pair is already subscribed 
 666    * to the CustomEvent passed in
 667    */
 668    Config.alreadySubscribed = function (evt, fn, obj) {
 669    
 670        var nSubscribers = evt.subscribers.length,
 671            subsc,
 672            i;
 673
 674        if (nSubscribers > 0) {
 675            i = nSubscribers - 1;
 676            do {
 677                subsc = evt.subscribers[i];
 678                if (subsc && subsc.obj == obj && subsc.fn == fn) {
 679                    return true;
 680                }
 681            }
 682            while (i--);
 683        }
 684
 685        return false;
 686
 687    };
 688
 689    YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
 690
 691}());
 692/**
 693* YAHOO.widget.DateMath is used for simple date manipulation. The class is a static utility
 694* used for adding, subtracting, and comparing dates.
 695* @namespace YAHOO.widget
 696* @class DateMath
 697*/
 698YAHOO.widget.DateMath = {
 699	/**
 700	* Constant field representing Day
 701	* @property DAY
 702	* @static
 703	* @final
 704	* @type String
 705	*/
 706	DAY : "D",
 707
 708	/**
 709	* Constant field representing Week
 710	* @property WEEK
 711	* @static
 712	* @final
 713	* @type String
 714	*/
 715	WEEK : "W",
 716
 717	/**
 718	* Constant field representing Year
 719	* @property YEAR
 720	* @static
 721	* @final
 722	* @type String
 723	*/
 724	YEAR : "Y",
 725
 726	/**
 727	* Constant field representing Month
 728	* @property MONTH
 729	* @static
 730	* @final
 731	* @type String
 732	*/
 733	MONTH : "M",
 734
 735	/**
 736	* Constant field representing one day, in milliseconds
 737	* @property ONE_DAY_MS
 738	* @static
 739	* @final
 740	* @type Number
 741	*/
 742	ONE_DAY_MS : 1000*60*60*24,
 743	
 744	/**
 745	 * Constant field representing the date in first week of January
 746	 * which identifies the first week of the year.
 747	 * <p>
 748	 * In the U.S, Jan 1st is normally used based on a Sunday start of week.
 749	 * ISO 8601, used widely throughout Europe, uses Jan 4th, based on a Monday start of week.
 750	 * </p>
 751	 * @property WEEK_ONE_JAN_DATE
 752	 * @static
 753	 * @type Number
 754	 */
 755	WEEK_ONE_JAN_DATE : 1,
 756
 757	/**
 758	* Adds the specified amount of time to the this instance.
 759	* @method add
 760	* @param {Date} date	The JavaScript Date object to perform addition on
 761	* @param {String} field	The field constant to be used for performing addition.
 762	* @param {Number} amount	The number of units (measured in the field constant) to add to the date.
 763	* @return {Date} The resulting Date object
 764	*/
 765	add : function(date, field, amount) {
 766		var d = new Date(date.getTime());
 767		switch (field) {
 768			case this.MONTH:
 769				var newMonth = date.getMonth() + amount;
 770				var years = 0;
 771
 772				if (newMonth < 0) {
 773					while (newMonth < 0) {
 774						newMonth += 12;
 775						years -= 1;
 776					}
 777				} else if (newMonth > 11) {
 778					while (newMonth > 11) {
 779						newMonth -= 12;
 780						years += 1;
 781					}
 782				}
 783
 784				d.setMonth(newMonth);
 785				d.setFullYear(date.getFullYear() + years);
 786				break;
 787			case this.DAY:
 788				this._addDays(d, amount);
 789				// d.setDate(date.getDate() + amount);
 790				break;
 791			case this.YEAR:
 792				d.setFullYear(date.getFullYear() + amount);
 793				break;
 794			case this.WEEK:
 795				this._addDays(d, (amount * 7));
 796				// d.setDate(date.getDate() + (amount * 7));
 797				break;
 798		}
 799		return d;
 800	},
 801
 802	/**
 803	 * Private helper method to account for bug in Safari 2 (webkit < 420)
 804	 * when Date.setDate(n) is called with n less than -128 or greater than 127.
 805	 * <p>
 806	 * Fix approach and original findings are available here:
 807	 * http://brianary.blogspot.com/2006/03/safari-date-bug.html
 808	 * </p>
 809	 * @method _addDays
 810	 * @param {Date} d JavaScript date object
 811	 * @param {Number} nDays The number of days to add to the date object (can be negative)
 812	 * @private
 813	 */
 814	_addDays : function(d, nDays) {
 815		if (YAHOO.env.ua.webkit && YAHOO.env.ua.webkit < 420) {
 816			if (nDays < 0) {
 817				// Ensure we don't go below -128 (getDate() is always 1 to 31, so we won't go above 127)
 818				for(var min = -128; nDays < min; nDays -= min) {
 819					d.setDate(d.getDate() + min);
 820				}
 821			} else {
 822				// Ensure we don't go above 96 + 31 = 127
 823				for(var max = 96; nDays > max; nDays -= max) {
 824					d.setDate(d.getDate() + max);
 825				}
 826			}
 827			// nDays should be remainder between -128 and 96
 828		}
 829		d.setDate(d.getDate() + nDays);
 830	},
 831
 832	/**
 833	* Subtracts the specified amount of time from the this instance.
 834	* @method subtract
 835	* @param {Date} date	The JavaScript Date object to perform subtraction on
 836	* @param {Number} field	The this field constant to be used for performing subtraction.
 837	* @param {Number} amount	The number of units (measured in the field constant) to subtract from the date.
 838	* @return {Date} The resulting Date object
 839	*/
 840	subtract : function(date, field, amount) {
 841		return this.add(date, field, (amount*-1));
 842	},
 843
 844	/**
 845	* Determines whether a given date is before another date on the calendar.
 846	* @method before
 847	* @param {Date} date		The Date object to compare with the compare argument
 848	* @param {Date} compareTo	The Date object to use for the comparison
 849	* @return {Boolean} true if the date occurs before the compared date; false if not.
 850	*/
 851	before : function(date, compareTo) {
 852		var ms = compareTo.getTime();
 853		if (date.getTime() < ms) {
 854			return true;
 855		} else {
 856			return false;
 857		}
 858	},
 859
 860	/**
 861	* Determines whether a given date is after another date on the calendar.
 862	* @method after
 863	* @param {Date} date		The Date object to compare with the compare argument
 864	* @param {Date} compareTo	The Date object to use for the comparison
 865	* @return {Boolean} true if the date occurs after the compared date; false if not.
 866	*/
 867	after : function(date, compareTo) {
 868		var ms = compareTo.getTime();
 869		if (date.getTime() > ms) {
 870			return true;
 871		} else {
 872			return false;
 873		}
 874	},
 875
 876	/**
 877	* Determines whether a given date is between two other dates on the calendar.
 878	* @method between
 879	* @param {Date} date		The date to check for
 880	* @param {Date} dateBegin	The start of the range
 881	* @param {Date} dateEnd		The end of the range
 882	* @return {Boolean} true if the date occurs between the compared dates; false if not.
 883	*/
 884	between : function(date, dateBegin, dateEnd) {
 885		if (this.after(date, dateBegin) && this.before(date, dateEnd)) {
 886			return true;
 887		} else {
 888			return false;
 889		}
 890	},
 891	
 892	/**
 893	* Retrieves a JavaScript Date object representing January 1 of any given year.
 894	* @method getJan1
 895	* @param {Number} calendarYear		The calendar year for which to retrieve January 1
 896	* @return {Date}	January 1 of the calendar year specified.
 897	*/
 898	getJan1 : function(calendarYear) {
 899		return this.getDate(calendarYear,0,1);
 900	},
 901
 902	/**
 903	* Calculates the number of days the specified date is from January 1 of the specified calendar year.
 904	* Passing January 1 to this function would return an offset value of zero.
 905	* @method getDayOffset
 906	* @param {Date}	date	The JavaScript date for which to find the offset
 907	* @param {Number} calendarYear	The calendar year to use for determining the offset
 908	* @return {Number}	The number of days since January 1 of the given year
 909	*/
 910	getDayOffset : function(date, calendarYear) {
 911		var beginYear = this.getJan1(calendarYear); // Find the start of the year. This will be in week 1.
 912		
 913		// Find the number of days the passed in date is away from the calendar year start
 914		var dayOffset = Math.ceil((date.getTime()-beginYear.getTime()) / this.ONE_DAY_MS);
 915		return dayOffset;
 916	},
 917
 918	/**
 919	* Calculates the week number for the given date. Can currently support standard
 920	* U.S. week numbers, based on Jan 1st defining the 1st week of the year, and 
 921	* ISO8601 week numbers, based on Jan 4th defining the 1st week of the year.
 922	* 
 923	* @method getWeekNumber
 924	* @param {Date}	date The JavaScript date for which to find the week number
 925	* @param {Number} firstDayOfWeek The index of the first day of the week (0 = Sun, 1 = Mon ... 6 = Sat).
 926	* Defaults to 0
 927	* @param {Number} janDate The date in the first week of January which defines week one for the year
 928	* Defaults to the value of YAHOO.widget.DateMath.WEEK_ONE_JAN_DATE, which is 1 (Jan 1st). 
 929	* For the U.S, this is normally Jan 1st. ISO8601 uses Jan 4th to define the first week of the year.
 930	* 
 931	* @return {Number} The number of the week containing the given date.
 932	*/
 933	getWeekNumber : function(date, firstDayOfWeek, janDate) {
 934
 935		// Setup Defaults
 936		firstDayOfWeek = firstDayOfWeek || 0;
 937		janDate = janDate || this.WEEK_ONE_JAN_DATE;
 938
 939		var targetDate = this.clearTime(date),
 940			startOfWeek,
 941			endOfWeek;
 942
 943		if (targetDate.getDay() === firstDayOfWeek) { 
 944			startOfWeek = targetDate;
 945		} else {
 946			startOfWeek = this.getFirstDayOfWeek(targetDate, firstDayOfWeek);
 947		}
 948
 949		var startYear = startOfWeek.getFullYear(),
 950			startTime = startOfWeek.getTime();
 951
 952		// DST shouldn't be a problem here, math is quicker than setDate();
 953		endOfWeek = new Date(startOfWeek.getTime() + 6*this.ONE_DAY_MS);
 954
 955		var weekNum;
 956		if (startYear !== endOfWeek.getFullYear() && endOfWeek.getDate() >= janDate) {
 957			// If years don't match, endOfWeek is in Jan. and if the 
 958			// week has WEEK_ONE_JAN_DATE in it, it's week one by definition.
 959			weekNum = 1;
 960		} else {
 961			// Get the 1st day of the 1st week, and 
 962			// find how many days away we are from it.
 963			var weekOne = this.clearTime(this.getDate(startYear, 0, janDate)),
 964				weekOneDayOne = this.getFirstDayOfWeek(weekOne, firstDayOfWeek);
 965
 966			// Round days to smoothen out 1 hr DST diff
 967			var daysDiff  = Math.round((targetDate.getTime() - weekOneDayOne.getTime())/this.ONE_DAY_MS);
 968
 969			// Calc. Full Weeks
 970			var rem = daysDiff % 7;
 971			var weeksDiff = (daysDiff - rem)/7;
 972			weekNum = weeksDiff + 1;
 973		}
 974		return weekNum;
 975	},
 976
 977	/**
 978	 * Get the first day of the week, for the give date. 
 979	 * @param {Date} dt The date in the week for which the first day is required.
 980	 * @param {Number} startOfWeek The index for the first day of the week, 0 = Sun, 1 = Mon ... 6 = Sat (defaults to 0)
 981	 * @return {Date} The first day of the week
 982	 */
 983	getFirstDayOfWeek : function (dt, startOfWeek) {
 984		startOfWeek = startOfWeek || 0;
 985		var dayOfWeekIndex = dt.getDay(),
 986			dayOfWeek = (dayOfWeekIndex - startOfWeek + 7) % 7;
 987
 988		return this.subtract(dt, this.DAY, dayOfWeek);
 989	},
 990
 991	/**
 992	* Determines if a given week overlaps two different years.
 993	* @method isYearOverlapWeek
 994	* @param {Date}	weekBeginDate	The JavaScript Date representing the first day of the week.
 995	* @return {Boolean}	true if the date overlaps two different years.
 996	*/
 997	isYearOverlapWeek : function(weekBeginDate) {
 998		var overlaps = false;
 999		var nextWeek = this.add(weekBeginDate, this.DAY, 6);
1000		if (nextWeek.getFullYear() != weekBeginDate.getFullYear()) {
1001			overlaps = true;
1002		}
1003		return overlaps;
1004	},
1005
1006	/**
1007	* Determines if a given week overlaps two different months.
1008	* @method isMonthOverlapWeek
1009	* @param {Date}	weekBeginDate	The JavaScript Date representing the first day of the week.
1010	* @return {Boolean}	true if the date overlaps two different months.
1011	*/
1012	isMonthOverlapWeek : function(weekBeginDate) {
1013		var overlaps = false;
1014		var nextWeek = this.add(weekBeginDate, this.DAY, 6);
1015		if (nextWeek.getMonth() != weekBeginDate.getMonth()) {
1016			overlaps = true;
1017		}
1018		return overlaps;
1019	},
1020
1021	/**
1022	* Gets the first day of a month containing a given date.
1023	* @method findMonthStart
1024	* @param {Date}	date	The JavaScript Date used to calculate the month start
1025	* @return {Date}		The JavaScript Date representing the first day of the month
1026	*/
1027	findMonthStart : function(date) {
1028		var start = this.getDate(date.getFullYear(), date.getMonth(), 1);
1029		return start;
1030	},
1031
1032	/**
1033	* Gets the last day of a month containing a given date.
1034	* @method findMonthEnd
1035	* @param {Date}	date	The JavaScript Date used to calculate the month end
1036	* @return {Date}		The JavaScript Date representing the last day of the month
1037	*/
1038	findMonthEnd : function(date) {
1039		var start = this.findMonthStart(date);
1040		var nextMonth = this.add(start, this.MONTH, 1);
1041		var end = this.subtract(nextMonth, this.DAY, 1);
1042		return end;
1043	},
1044
1045	/**
1046	* Clears the time fields from a given date, effectively setting the time to 12 noon.
1047	* @method clearTime
1048	* @param {Date}	date	The JavaScript Date for which the time fields will be cleared
1049	* @return {Date}		The JavaScript Date cleared of all time fields
1050	*/
1051	clearTime : function(date) {
1052		date.setHours(12,0,0,0);
1053		return date;
1054	},
1055
1056	/**
1057	 * Returns a new JavaScript Date object, representing the given year, month and date. Time fields (hr, min, sec, ms) on the new Date object
1058	 * are set to 0. The method allows Date instances to be created with the a year less than 100. "new Date(year, month, date)" implementations 
1059	 * set the year to 19xx if a year (xx) which is less than 100 is provided.
1060	 * <p>
1061	 * <em>NOTE:</em>Validation on argument values is not performed. It is the caller's responsibility to ensure
1062	 * arguments are valid as per the ECMAScript-262 Date object specification for the new Date(year, month[, date]) constructor.
1063	 * </p>
1064	 * @method getDate
1065	 * @param {Number} y Year.
1066	 * @param {Number} m Month index from 0 (Jan) to 11 (Dec).
1067	 * @param {Number} d (optional) Date from 1 to 31. If not provided, defaults to 1.
1068	 * @return {Date} The JavaScript date object with year, month, date set as provided.
1069	 */
1070	getDate : function(y, m, d) {
1071		var dt = null;
1072		if (YAHOO.lang.isUndefined(d)) {
1073			d = 1;
1074		}
1075		if (y >= 100) {
1076			dt = new Date(y, m, d);
1077		} else {
1078			dt = new Date();
1079			dt.setFullYear(y);
1080			dt.setMonth(m);
1081			dt.setDate(d);
1082			dt.setHours(0,0,0,0);
1083		}
1084		return dt;
1085	}
1086};
1087
1088/**
1089* 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
1090* multi-month interface. Calendars are generated entirely via script and can be navigated without any page refreshes.
1091* @module    calendar
1092* @title    Calendar
1093* @namespace  YAHOO.widget
1094* @requires  yahoo,dom,event
1095*/
1096(function(){
1097
1098	var Dom = YAHOO.util.Dom,
1099		Event = YAHOO.util.Event,
1100		Lang = YAHOO.lang,
1101		DateMath = YAHOO.widget.DateMath;
1102
1103/**
1104* Calendar is the base class for the Calendar widget. In its most basic
1105* implementation, it has the ability to render a calendar widget on the page
1106* that can be manipulated to select a single date, move back and forth between
1107* months and years.
1108* <p>To construct the placeholder for the calendar widget, the code is as
1109* follows:
1110*	<xmp>
1111*		<div id="calContainer"></div>
1112*	</xmp>
1113* </p>
1114* <p>
1115* <strong>NOTE: As of 2.4.0, the constructor's ID argument is optional.</strong>
1116* The Calendar can be constructed by simply providing a container ID string, 
1117* or a reference to a container DIV HTMLElement (the element needs to exist 
1118* in the document).
1119* 
1120* E.g.:
1121*	<xmp>
1122*		var c = new YAHOO.widget.Calendar("calContainer", configOptions);
1123*	</xmp>
1124* or:
1125*   <xmp>
1126*       var containerDiv = YAHOO.util.Dom.get("calContainer");
1127*		var c = new YAHOO.widget.Calendar(containerDiv, configOptions);
1128*	</xmp>
1129* </p>
1130* <p>
1131* If not provided, the ID will be generated from the container DIV ID by adding an "_t" suffix.
1132* For example if an ID is not provided, and the container's ID is "calContainer", the Calendar's ID will be set to "calContainer_t".
1133* </p>
1134* 
1135* @namespace YAHOO.widget
1136* @class Calendar
1137* @constructor
1138* @param {String} id optional The id of the table element that will represent the Calendar widget. As of 2.4.0, this argument is optional.
1139* @param {String | HTMLElement} container The id of the container div element that will wrap the Calendar table, or a reference to a DIV element which exists in the document.
1140* @param {Object} config optional The configuration object containing the initial configuration values for the Calendar.
1141*/
1142function Calendar(id, containerId, config) {
1143	this.init.apply(this, arguments);
1144}
1145
1146/**
1147* The path to be used for images loaded for the Calendar
1148* @property YAHOO.widget.Calendar.IMG_ROOT
1149* @static
1150* @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
1151* @type String
1152*/
1153Calendar.IMG_ROOT = null;
1154
1155/**
1156* Type constant used for renderers to represent an individual date (M/D/Y)
1157* @property YAHOO.widget.Calendar.DATE
1158* @static
1159* @final
1160* @type String
1161*/
1162Calendar.DATE = "D";
1163
1164/**
1165* Type constant used for renderers to represent an individual date across any year (M/D)
1166* @property YAHOO.widget.Calendar.MONTH_DAY
1167* @static
1168* @final
1169* @type String
1170*/
1171Calendar.MONTH_DAY = "MD";
1172
1173/**
1174* Type constant used for renderers to represent a weekday
1175* @property YAHOO.widget.Calendar.WEEKDAY
1176* @static
1177* @final
1178* @type String
1179*/
1180Calendar.WEEKDAY = "WD";
1181
1182/**
1183* Type constant used for renderers to represent a range of individual dates (M/D/Y-M/D/Y)
1184* @property YAHOO.widget.Calendar.RANGE
1185* @static
1186* @final
1187* @type String
1188*/
1189Calendar.RANGE = "R";
1190
1191/**
1192* Type constant used for renderers to represent a month across any year
1193* @property YAHOO.widget.Calendar.MONTH
1194* @static
1195* @final
1196* @type String
1197*/
1198Calendar.MONTH = "M";
1199
1200/**
1201* Constant that represents the total number of date cells that are displayed in a given month
1202* @property YAHOO.widget.Calendar.DISPLAY_DAYS
1203* @static
1204* @final
1205* @type Number
1206*/
1207Calendar.DISPLAY_DAYS = 42;
1208
1209/**
1210* Constant used for halting the execution of the remainder of the render stack
1211* @property YAHOO.widget.Calendar.STOP_RENDER
1212* @static
1213* @final
1214* @type String
1215*/
1216Calendar.STOP_RENDER = "S";
1217
1218/**
1219* Constant used to represent short date field string formats (e.g. Tu or Feb)
1220* @property YAHOO.widget.Calendar.SHORT
1221* @static
1222* @final
1223* @type String
1224*/
1225Calendar.SHORT = "short";
1226
1227/**
1228* Constant used to represent long date field string formats (e.g. Monday or February)
1229* @property YAHOO.widget.Calendar.LONG
1230* @static
1231* @final
1232* @type String
1233*/
1234Calendar.LONG = "long";
1235
1236/**
1237* Constant used to represent medium date field string formats (e.g. Mon)
1238* @property YAHOO.widget.Calendar.MEDIUM
1239* @static
1240* @final
1241* @type String
1242*/
1243Calendar.MEDIUM = "medium";
1244
1245/**
1246* Constant used to represent single character date field string formats (e.g. M, T, W)
1247* @property YAHOO.widget.Calendar.ONE_CHAR
1248* @static
1249* @final
1250* @type String
1251*/
1252Calendar.ONE_CHAR = "1char";
1253
1254/**
1255* The set of default Config property keys and values for the Calendar
1256* @property YAHOO.widget.Calendar._DEFAULT_CONFIG
1257* @final
1258* @static
1259* @private
1260* @type Object
1261*/
1262Calendar._DEFAULT_CONFIG = {
1263	// Default values for pagedate and selected are not class level constants - they are set during instance creation 
1264	PAGEDATE : {key:"pagedate", value:null},
1265	SELECTED : {key:"selected", value:null},
1266	TITLE : {key:"title", value:""},
1267	CLOSE : {key:"close", value:false},
1268	IFRAME : {key:"iframe", value:(YAHOO.env.ua.ie && YAHOO.env.ua.ie <= 6) ? true : false},
1269	MINDATE : {key:"mindate", value:null},
1270	MAXDATE : {key:"maxdate", value:null},
1271	MULTI_SELECT : {key:"multi_select", value:false},
1272	START_WEEKDAY : {key:"start_weekday", value:0},
1273	SHOW_WEEKDAYS : {key:"show_weekdays", value:true},
1274	SHOW_WEEK_HEADER : {key:"show_week_header", value:false},
1275	SHOW_WEEK_FOOTER : {key:"show_week_footer", value:false},
1276	HIDE_BLANK_WEEKS : {key:"hide_blank_weeks", value:false},
1277	NAV_ARROW_LEFT: {key:"nav_arrow_left", value:null} ,
1278	NAV_ARROW_RIGHT : {key:"nav_arrow_right", value:null} ,
1279	MONTHS_SHORT : {key:"months_short", value:["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]},
1280	MONTHS_LONG: {key:"months_long", value:["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]},
1281	WEEKDAYS_1CHAR: {key:"weekdays_1char", value:["S", "M", "T", "W", "T", "F", "S"]},
1282	WEEKDAYS_SHORT: {key:"weekdays_short", value:["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]},
1283	WEEKDAYS_MEDIUM: {key:"weekdays_medium", value:["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]},
1284	WEEKDAYS_LONG: {key:"weekdays_long", value:["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]},
1285	LOCALE_MONTHS:{key:"locale_months", value:"long"},
1286	LOCALE_WEEKDAYS:{key:"locale_weekdays", value:"short"},
1287	DATE_DELIMITER:{key:"date_delimiter", value:","},
1288	DATE_FIELD_DELIMITER:{key:"date_field_delimiter", value:"/"},
1289	DATE_RANGE_DELIMITER:{key:"date_range_delimiter", value:"-"},
1290	MY_MONTH_POSITION:{key:"my_month_position", value:1},
1291	MY_YEAR_POSITION:{key:"my_year_position", value:2},
1292	MD_MONTH_POSITION:{key:"md_month_position", value:1},
1293	MD_DAY_POSITION:{key:"md_day_position", value:2},
1294	MDY_MONTH_POSITION:{key:"mdy_month_position", value:1},
1295	MDY_DAY_POSITION:{key:"mdy_day_position", value:2},
1296	MDY_YEAR_POSITION:{key:"mdy_year_position", value:3},
1297	MY_LABEL_MONTH_POSITION:{key:"my_label_month_position", value:1},
1298	MY_LABEL_YEAR_POSITION:{key:"my_label_year_position", value:2},
1299	MY_LABEL_MONTH_SUFFIX:{key:"my_label_month_suffix", value:" "},
1300	MY_LABEL_YEAR_SUFFIX:{key:"my_label_year_suffix", value:""},
1301	NAV: {key:"navigator", value: null},
1302	STRINGS : { 
1303		key:"strings",
1304		value: {
1305			previousMonth : "Previous Month",
1306			nextMonth : "Next Month",
1307			close: "Close"
1308		},
1309		supercedes : ["close", "title"]
1310	}
1311};
1312
1313var DEF_CFG = Calendar._DEFAULT_CONFIG;
1314
1315/**
1316* The set of Custom Event types supported by the Calendar
1317* @property YAHOO.widget.Calendar._EVENT_TYPES
1318* @final
1319* @static
1320* @private
1321* @type Object
1322*/
1323Calendar._EVENT_TYPES = {
1324	BEFORE_SELECT : "beforeSelect", 
1325	SELECT : "select",
1326	BEFORE_DESELECT : "beforeDeselect",
1327	DESELECT : "deselect",
1328	CHANGE_PAGE : "changePage",
1329	BEFORE_RENDER : "beforeRender",
1330	RENDER : "render",
1331	BEFORE_DESTROY : "beforeDestroy",
1332	DESTROY : "destroy",
1333	RESET : "reset",
1334	CLEAR : "clear",
1335	BEFORE_HIDE : "beforeHide",
1336	HIDE : "hide",
1337	BEFORE_SHOW : "beforeShow",
1338	SHOW : "show",
1339	BEFORE_HIDE_NAV : "beforeHideNav",
1340	HIDE_NAV : "hideNav",
1341	BEFORE_SHOW_NAV : "beforeShowNav",
1342	SHOW_NAV : "showNav",
1343	BEFORE_RENDER_NAV : "beforeRenderNav",
1344	RENDER_NAV : "renderNav"
1345};
1346
1347/**
1348* The set of default style constants for the Calendar
1349* @property YAHOO.widget.Calendar._STYLES
1350* @final
1351* @static
1352* @private
1353* @type Object
1354*/
1355Calendar._STYLES = {
1356	CSS_ROW_HEADER: "calrowhead",
1357	CSS_ROW_FOOTER: "calrowfoot",
1358	CSS_CELL : "calcell",
1359	CSS_CELL_SELECTOR : "selector",
1360	CSS_CELL_SELECTED : "selected",
1361	CSS_CELL_SELECTABLE : "selectable",
1362	CSS_CELL_RESTRICTED : "restricted",
1363	CSS_CELL_TODAY : "today",
1364	CSS_CELL_OOM : "oom",
1365	CSS_CELL_OOB : "previous",
1366	CSS_HEADER : "calheader",
1367	CSS_HEADER_TEXT : "calhead",
1368	CSS_BODY : "calbody",
1369	CSS_WEEKDAY_CELL : "calweekdaycell",
1370	CSS_WEEKDAY_ROW : "calweekdayrow",
1371	CSS_FOOTER : "calfoot",
1372	CSS_CALENDAR : "yui-calendar",
1373	CSS_SINGLE : "single",
1374	CSS_CONTAINER : "yui-calcontainer",
1375	CSS_NAV_LEFT : "calnavleft",
1376	CSS_NAV_RIGHT : "calnavright",
1377	CSS_NAV : "calnav",
1378	CSS_CLOSE : "calclose",
1379	CSS_CELL_TOP : "calcelltop",
1380	CSS_CELL_LEFT : "calcellleft",
1381	CSS_CELL_RIGHT : "calcellright",
1382	CSS_CELL_BOTTOM : "calcellbottom",
1383	CSS_CELL_HOVER : "calcellhover",
1384	CSS_CELL_HIGHLIGHT1 : "highlight1",
1385	CSS_CELL_HIGHLIGHT2 : "highlight2",
1386	CSS_CELL_HIGHLIGHT3 : "highlight3",
1387	CSS_CELL_HIGHLIGHT4 : "highlight4"
1388};
1389
1390Calendar.prototype = {
1391
1392	/**
1393	* The configuration object used to set up the calendars various locale and style options.
1394	* @property Config
1395	* @private
1396	* @deprecated Configuration properties should be set by calling Calendar.cfg.setProperty.
1397	* @type Object
1398	*/
1399	Config : null,
1400
1401	/**
1402	* The parent CalendarGroup, only to be set explicitly by the parent group
1403	* @property parent
1404	* @type CalendarGroup
1405	*/	
1406	parent : null,
1407
1408	/**
1409	* The index of this item in the parent group
1410	* @property index
1411	* @type Number
1412	*/
1413	index : -1,
1414
1415	/**
1416	* The collection of calendar table cells
1417	* @property cells
1418	* @type HTMLTableCellElement[]
1419	*/
1420	cells : null,
1421
1422	/**
1423	* 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].
1424	* @property cellDates
1425	* @type Array[](Number[])
1426	*/
1427	cellDates : null,
1428
1429	/**
1430	* The id that uniquely identifies this Calendar.
1431	* @property id
1432	* @type String
1433	*/
1434	id : null,
1435
1436	/**
1437	* The unique id associated with the Calendar's container
1438	* @property containerId
1439	* @type String
1440	*/
1441	containerId: null,
1442
1443	/**
1444	* 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.
1445	* @property oDomContainer
1446	* @type HTMLElement
1447	*/
1448	oDomContainer : null,
1449
1450	/**
1451	* A Date object representing today's date.
1452	* @property today
1453	* @type Date
1454	*/
1455	today : null,
1456
1457	/**
1458	* The list of render functions, along with required parameters, used to render cells. 
1459	* @property renderStack
1460	* @type Array[]
1461	*/
1462	renderStack : null,
1463
1464	/**
1465	* A copy of the initial render functions created before rendering.
1466	* @property _renderStack
1467	* @private
1468	* @type Array
1469	*/
1470	_renderStack : null,
1471
1472	/**
1473	* A reference to the CalendarNavigator instance created for this Calendar.
1474	* Will be null if the "navigator" configuration property has not been set
1475	* @property oNavigator
1476	* @type CalendarNavigator
1477	*/
1478	oNavigator : null,
1479
1480	/**
1481	* The private list of initially selected dates.
1482	* @property _selectedDates
1483	* @private
1484	* @type Array
1485	*/
1486	_selectedDates : null,
1487
1488	/**
1489	* A map of DOM event handlers to attach to cells associated with specific CSS class names
1490	* @property domEventMap
1491	* @type Object
1492	*/
1493	domEventMap : null,
1494
1495	/**
1496	 * Protected helper used to parse Calendar constructor/init arguments.
1497	 *
1498	 * As of 2.4.0, Calendar supports a simpler constructor 
1499	 * signature. This method reconciles arguments
1500	 * received in the pre 2.4.0 and 2.4.0 formats.
1501	 * 
1502	 * @protected
1503	 * @method _parseArgs
1504	 * @param {Array} Function "arguments" array
1505	 * @return {Object} Object with id, container, config properties containing
1506	 * the reconciled argument values.
1507	 **/
1508	_parseArgs : function(args) {
1509		/*
1510		   2.4.0 Constructors signatures
1511
1512		   new Calendar(String)
1513		   new Calendar(HTMLElement)
1514		   new Calendar(String, ConfigObject)
1515		   new Calendar(HTMLElement, ConfigObject)
1516
1517		   Pre 2.4.0 Constructor signatures
1518
1519		   new Calendar(String, String)
1520		   new Calendar(String, HTMLElement)
1521		   new Calendar(String, String, ConfigObject)
1522		   new Calendar(String, HTMLElement, ConfigObject)
1523		 */
1524		var nArgs = {id:null, container:null, config:null};
1525
1526		if (args && args.length && args.length > 0) {
1527			switch (args.length) {
1528				case 1:
1529					nArgs.id = null;
1530					nArgs.container = args[0];
1531					nArgs.config = null;
1532					break;
1533				case 2:
1534					if (Lang.isObject(args[1]) && !args[1].tagName && !(args[1] instanceof String)) {
1535						nArgs.id = null;
1536						nArgs.container = args[0];
1537						nArgs.config = args[1];
1538					} else {
1539						nArgs.id = args[0];
1540						nArgs.container = args[1];
1541						nArgs.config = null;
1542					}
1543					break;
1544				default: // 3+
1545					nArgs.id = args[0];
1546					nArgs.container = args[1];
1547					nArgs.config = args[2];
1548					break;
1549			}
1550		} else {
1551		}
1552		return nArgs;
1553	},
1554
1555	/**
1556	* Initializes the Calendar widget.
1557	* @method init
1558	*
1559	* @param {String} id optional The id of the table element that will represent the Calendar widget. As of 2.4.0, this argument is optional.
1560	* @param {String | HTMLElement} container The id of the container div element that will wrap the Calendar table, or a reference to a DIV element which exists in the document.
1561	* @param {Object} config optional The configuration object containing the initial configuration values for the Calendar.
1562	*/
1563	init : function(id, container, config) {
1564		// Normalize 2.4.0, pre 2.4.0 args
1565		var nArgs = this._parseArgs(arguments);
1566
1567		id = nArgs.id;
1568		container = nArgs.container;
1569		config = nArgs.config;
1570
1571		this.oDomContainer = Dom.get(container);
1572
1573		if (!this.oDomContainer.id) {
1574			this.oDomContainer.id = Dom.generateId();
1575		}
1576		if (!id) {
1577			id = this.oDomContainer.id + "_t";
1578		}
1579
1580		this.id = id;
1581		this.containerId = this.oDomContainer.id;
1582
1583		this.initEvents();
1584
1585		this.today = new Date();
1586		DateMath.clearTime(this.today);
1587
1588		/**
1589		* The Config object used to hold the configuration variables for the Calendar
1590		* @property cfg
1591		* @type YAHOO.util.Config
1592		*/
1593		this.cfg = new YAHOO.util.Config(this);
1594
1595		/**
1596		* The local object which contains the Calendar's options
1597		* @property Options
1598		* @type Object
1599		*/
1600		this.Options = {};
1601
1602		/**
1603		* The local object which contains the Calendar's locale settings
1604		* @property Locale
1605		* @type Object
1606		*/
1607		this.Locale = {};
1608
1609		this.initStyles();
1610
1611		Dom.addClass(this.oDomContainer, this.Style.CSS_CONTAINER);
1612		Dom.addClass(this.oDomContainer, this.Style.CSS_SINGLE);
1613
1614		this.cellDates = [];
1615		this.cells = [];
1616		this.renderStack = [];
1617		this._renderStack = [];
1618
1619		this.setupConfig();
1620
1621		if (config) {
1622			this.cfg.applyConfig(config, true);
1623		}
1624
1625		this.cfg.fireQueue();
1626	},
1627
1628	/**
1629	* Default Config listener for the iframe property. If the iframe config property is set to true, 
1630	* renders the built-in IFRAME shim if the container is relatively or absolutely positioned.
1631	* 
1632	* @method configIframe
1633	*/
1634	configIframe : function(type, args, obj) {
1635		var useIframe = args[0]

Large files files are truncated, but you can click here to view the full file