2
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3
Code licensed under the BSD License:
4
http://developer.yahoo.net/yui/license.txt
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
18
* @param {Object} owner The owner Object to which this Config Object belongs
20
YAHOO.util.Config = function (owner) {
30
var Lang = YAHOO.lang,
31
CustomEvent = YAHOO.util.CustomEvent,
32
Config = YAHOO.util.Config;
36
* Constant representing the CustomEvent type for the config changed event.
37
* @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
42
Config.CONFIG_CHANGED_EVENT = "configChanged";
45
* Constant representing the boolean type string
46
* @property YAHOO.util.Config.BOOLEAN_TYPE
51
Config.BOOLEAN_TYPE = "boolean";
56
* Object reference to the owner of this Config Object
63
* Boolean flag that specifies whether a queue is currently
65
* @property queueInProgress
68
queueInProgress: false,
71
* Maintains the local collection of configuration property objects and
72
* their specified values
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
90
* Maintains the local, normalized CustomEvent queue
91
* @property eventQueue
98
* Custom Event, notifying subscribers when Config properties are set
99
* (setProperty is called without the silent flag
100
* @event configChangedEvent
102
configChangedEvent: null,
105
* Initializes the configuration Object and all of its local members.
107
* @param {Object} owner The owner Object to which this Config
110
init: function (owner) {
114
this.configChangedEvent =
115
this.createEvent(Config.CONFIG_CHANGED_EVENT);
117
this.configChangedEvent.signature = CustomEvent.LIST;
118
this.queueInProgress = false;
120
this.initialConfig = {};
121
this.eventQueue = [];
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
131
checkBoolean: function (val) {
132
return (typeof val == Config.BOOLEAN_TYPE);
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
141
checkNumber: function (val) {
142
return (!isNaN(val));
146
* Fires a configuration property event using the specified value.
149
* @param {String} key The configuration property's name
150
* @param {value} Object The value of the correct type for the property
152
fireEvent: function ( key, value ) {
153
var property = this.config[key];
155
if (property && property.event) {
156
property.event.fire(value);
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
167
addProperty: function ( key, propertyObject ) {
168
key = key.toLowerCase();
170
this.config[key] = propertyObject;
172
propertyObject.event = this.createEvent(key, { scope: this.owner });
173
propertyObject.event.signature = CustomEvent.LIST;
176
propertyObject.key = key;
178
if (propertyObject.handler) {
179
propertyObject.event.subscribe(propertyObject.handler,
183
this.setProperty(key, propertyObject.value, true);
185
if (! propertyObject.suppressEvent) {
186
this.queueProperty(key, propertyObject.value);
192
* Returns a key-value configuration map of the values currently set in
195
* @return {Object} The current config, represented in a key-value map
197
getConfig: function () {
200
currCfg = this.config,
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;
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
222
getProperty: function (key) {
223
var property = this.config[key.toLowerCase()];
224
if (property && property.event) {
225
return property.value;
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
237
resetProperty: function (key) {
239
key = key.toLowerCase();
241
var property = this.config[key];
243
if (property && property.event) {
245
if (this.initialConfig[key] &&
246
!Lang.isUndefined(this.initialConfig[key])) {
248
this.setProperty(key, this.initialConfig[key]);
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.
271
setProperty: function (key, value, silent) {
275
key = key.toLowerCase();
277
if (this.queueInProgress && ! silent) {
278
// Currently running through a queue...
279
this.queueProperty(key,value);
283
property = this.config[key];
284
if (property && property.event) {
285
if (property.validator && !property.validator(value)) {
288
property.value = value;
290
this.fireEvent(key, value);
291
this.configChangedEvent.fire([key, value]);
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
311
queueProperty: function (key, value) {
313
key = key.toLowerCase();
315
var property = this.config[key],
316
foundDuplicate = false,
331
if (property && property.event) {
333
if (!Lang.isUndefined(value) && property.validator &&
334
!property.validator(value)) { // validator
338
if (!Lang.isUndefined(value)) {
339
property.value = value;
341
value = property.value;
344
foundDuplicate = false;
345
iLen = this.eventQueue.length;
347
for (i = 0; i < iLen; i++) {
348
queueItem = this.eventQueue[i];
351
queueItemKey = queueItem[0];
352
queueItemValue = queueItem[1];
354
if (queueItemKey == key) {
357
found a dupe... push to end of queue, null
358
current item, and break
361
this.eventQueue[i] = null;
363
this.eventQueue.push(
364
[key, (!Lang.isUndefined(value) ?
365
value : queueItemValue)]);
367
foundDuplicate = true;
373
// this is a refire, or a new property in the queue
375
if (! foundDuplicate && !Lang.isUndefined(value)) {
376
this.eventQueue.push([key, value]);
380
if (property.supercedes) {
382
sLen = property.supercedes.length;
384
for (s = 0; s < sLen; s++) {
386
supercedesCheck = property.supercedes[s];
387
qLen = this.eventQueue.length;
389
for (q = 0; q < qLen; q++) {
390
queueItemCheck = this.eventQueue[q];
392
if (queueItemCheck) {
393
queueItemCheckKey = queueItemCheck[0];
394
queueItemCheckValue = queueItemCheck[1];
396
if (queueItemCheckKey ==
397
supercedesCheck.toLowerCase() ) {
399
this.eventQueue.push([queueItemCheckKey,
400
queueItemCheckValue]);
402
this.eventQueue[q] = null;
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
423
refireEvent: function (key) {
425
key = key.toLowerCase();
427
var property = this.config[key];
429
if (property && property.event &&
431
!Lang.isUndefined(property.value)) {
433
if (this.queueInProgress) {
435
this.queueProperty(key);
439
this.fireEvent(key, property.value);
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.
457
applyConfig: function (userConfig, init) {
464
for (sKey in userConfig) {
465
if (Lang.hasOwnProperty(userConfig, sKey)) {
466
oConfig[sKey.toLowerCase()] = userConfig[sKey];
469
this.initialConfig = oConfig;
472
for (sKey in userConfig) {
473
if (Lang.hasOwnProperty(userConfig, sKey)) {
474
this.queueProperty(sKey, userConfig[sKey]);
480
* Refires the events for all configuration properties using their
484
refresh: function () {
488
for (prop in this.config) {
489
if (Lang.hasOwnProperty(this.config, prop)) {
490
this.refireEvent(prop);
496
* Fires the normalized list of queued property change events
499
fireQueue: function () {
507
this.queueInProgress = true;
508
for (i = 0;i < this.eventQueue.length; i++) {
509
queueItem = this.eventQueue[i];
513
value = queueItem[1];
514
property = this.config[key];
516
property.value = value;
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;
523
this.fireEvent(key,value);
527
this.queueInProgress = false;
528
this.eventQueue = [];
532
* Subscribes an external handler to the change event for any
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,
545
subscribeToConfigEvent: function (key, handler, obj, override) {
547
var property = this.config[key.toLowerCase()];
549
if (property && property.event) {
550
if (!Config.alreadySubscribed(property.event, handler, obj)) {
551
property.event.subscribe(handler, obj, override);
561
* Unsubscribes an external handler from the change event for any
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,
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);
582
* Returns a string representation of the Config object
584
* @return {String} The Config object in string format.
586
toString: function () {
587
var output = "Config";
589
output += " [" + this.owner.toString() + "]";
595
* Returns a string representation of the Config object's current
597
* @method outputEventQueue
598
* @return {String} The string list of CustomEvents currently queued
601
outputEventQueue: function () {
606
nQueue = this.eventQueue.length;
608
for (q = 0; q < nQueue; q++) {
609
queueItem = this.eventQueue[q];
611
output += queueItem[0] + "=" + queueItem[1] + ", ";
618
* Sets all properties to null, unsubscribes all listeners from each
619
* property's change event and all listeners from the configChangedEvent.
622
destroy: function () {
624
var oConfig = this.config,
629
for (sProperty in oConfig) {
631
if (Lang.hasOwnProperty(oConfig, sProperty)) {
633
oProperty = oConfig[sProperty];
635
oProperty.event.unsubscribeAll();
636
oProperty.event = null;
642
this.configChangedEvent.unsubscribeAll();
644
this.configChangedEvent = null;
647
this.initialConfig = null;
648
this.eventQueue = null;
657
* Checks to determine if a particular function/Object pair are already
658
* subscribed to the specified CustomEvent
659
* @method YAHOO.util.Config.alreadySubscribed
661
* @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check
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
668
Config.alreadySubscribed = function (evt, fn, obj) {
670
var nSubscribers = evt.subscribers.length,
674
if (nSubscribers > 0) {
675
i = nSubscribers - 1;
677
subsc = evt.subscribers[i];
678
if (subsc && subsc.obj == obj && subsc.fn == fn) {
689
YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
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
698
YAHOO.widget.DateMath = {
700
* Constant field representing Day
709
* Constant field representing Week
718
* Constant field representing Year
727
* Constant field representing Month
736
* Constant field representing one day, in milliseconds
737
* @property ONE_DAY_MS
742
ONE_DAY_MS : 1000*60*60*24,
745
* Constant field representing the date in first week of January
746
* which identifies the first week of the year.
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.
751
* @property WEEK_ONE_JAN_DATE
755
WEEK_ONE_JAN_DATE : 1,
758
* Adds the specified amount of time to the this instance.
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
765
add : function(date, field, amount) {
766
var d = new Date(date.getTime());
769
var newMonth = date.getMonth() + amount;
773
while (newMonth < 0) {
777
} else if (newMonth > 11) {
778
while (newMonth > 11) {
784
d.setMonth(newMonth);
785
d.setFullYear(date.getFullYear() + years);
788
this._addDays(d, amount);
789
// d.setDate(date.getDate() + amount);
792
d.setFullYear(date.getFullYear() + amount);
795
this._addDays(d, (amount * 7));
796
// d.setDate(date.getDate() + (amount * 7));
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.
806
* Fix approach and original findings are available here:
807
* http://brianary.blogspot.com/2006/03/safari-date-bug.html
810
* @param {Date} d JavaScript date object
811
* @param {Number} nDays The number of days to add to the date object (can be negative)
814
_addDays : function(d, nDays) {
815
if (YAHOO.env.ua.webkit && YAHOO.env.ua.webkit < 420) {
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);
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);
827
// nDays should be remainder between -128 and 96
829
d.setDate(d.getDate() + nDays);
833
* Subtracts the specified amount of time from the this instance.
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
840
subtract : function(date, field, amount) {
841
return this.add(date, field, (amount*-1));
845
* Determines whether a given date is before another date on the calendar.
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.
851
before : function(date, compareTo) {
852
var ms = compareTo.getTime();
853
if (date.getTime() < ms) {
861
* Determines whether a given date is after another date on the calendar.
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.
867
after : function(date, compareTo) {
868
var ms = compareTo.getTime();
869
if (date.getTime() > ms) {
877
* Determines whether a given date is between two other dates on the calendar.
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.
884
between : function(date, dateBegin, dateEnd) {
885
if (this.after(date, dateBegin) && this.before(date, dateEnd)) {
893
* Retrieves a JavaScript Date object representing January 1 of any given year.
895
* @param {Number} calendarYear The calendar year for which to retrieve January 1
896
* @return {Date} January 1 of the calendar year specified.
898
getJan1 : function(calendarYear) {
899
return this.getDate(calendarYear,0,1);
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
910
getDayOffset : function(date, calendarYear) {
911
var beginYear = this.getJan1(calendarYear); // Find the start of the year. This will be in week 1.
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);
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.
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).
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.
931
* @return {Number} The number of the week containing the given date.
933
getWeekNumber : function(date, firstDayOfWeek, janDate) {
936
firstDayOfWeek = firstDayOfWeek || 0;
937
janDate = janDate || this.WEEK_ONE_JAN_DATE;
939
var targetDate = this.clearTime(date),
943
if (targetDate.getDay() === firstDayOfWeek) {
944
startOfWeek = targetDate;
946
startOfWeek = this.getFirstDayOfWeek(targetDate, firstDayOfWeek);
949
var startYear = startOfWeek.getFullYear(),
950
startTime = startOfWeek.getTime();
952
// DST shouldn't be a problem here, math is quicker than setDate();
953
endOfWeek = new Date(startOfWeek.getTime() + 6*this.ONE_DAY_MS);
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.
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);
966
// Round days to smoothen out 1 hr DST diff
967
var daysDiff = Math.round((targetDate.getTime() - weekOneDayOne.getTime())/this.ONE_DAY_MS);
970
var rem = daysDiff % 7;
971
var weeksDiff = (daysDiff - rem)/7;
972
weekNum = weeksDiff + 1;
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
983
getFirstDayOfWeek : function (dt, startOfWeek) {
984
startOfWeek = startOfWeek || 0;
985
var dayOfWeekIndex = dt.getDay(),
986
dayOfWeek = (dayOfWeekIndex - startOfWeek + 7) % 7;
988
return this.subtract(dt, this.DAY, dayOfWeek);
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.
997
isYearOverlapWeek : function(weekBeginDate) {
998
var overlaps = false;
999
var nextWeek = this.add(weekBeginDate, this.DAY, 6);
1000
if (nextWeek.getFullYear() != weekBeginDate.getFullYear()) {
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.
1012
isMonthOverlapWeek : function(weekBeginDate) {
1013
var overlaps = false;
1014
var nextWeek = this.add(weekBeginDate, this.DAY, 6);
1015
if (nextWeek.getMonth() != weekBeginDate.getMonth()) {
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
1027
findMonthStart : function(date) {
1028
var start = this.getDate(date.getFullYear(), date.getMonth(), 1);
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
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);
1046
* Clears the time fields from a given date, effectively setting the time to 12 noon.
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
1051
clearTime : function(date) {
1052
date.setHours(12,0,0,0);
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.
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.
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.
1070
getDate : function(y, m, d) {
1072
if (YAHOO.lang.isUndefined(d)) {
1076
dt = new Date(y, m, d);
1082
dt.setHours(0,0,0,0);
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.
1093
* @namespace YAHOO.widget
1094
* @requires yahoo,dom,event
1098
var Dom = YAHOO.util.Dom,
1099
Event = YAHOO.util.Event,
1101
DateMath = YAHOO.widget.DateMath;
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
1108
* <p>To construct the placeholder for the calendar widget, the code is as
1111
* <div id="calContainer"></div>
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
1122
* var c = new YAHOO.widget.Calendar("calContainer", configOptions);
1126
* var containerDiv = YAHOO.util.Dom.get("calContainer");
1127
* var c = new YAHOO.widget.Calendar(containerDiv, configOptions);
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".
1135
* @namespace YAHOO.widget
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.
1142
function Calendar(id, containerId, config) {
1143
this.init.apply(this, arguments);
1147
* The path to be used for images loaded for the Calendar
1148
* @property YAHOO.widget.Calendar.IMG_ROOT
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
1153
Calendar.IMG_ROOT = null;
1156
* Type constant used for renderers to represent an individual date (M/D/Y)
1157
* @property YAHOO.widget.Calendar.DATE
1162
Calendar.DATE = "D";
1165
* Type constant used for renderers to represent an individual date across any year (M/D)
1166
* @property YAHOO.widget.Calendar.MONTH_DAY
1171
Calendar.MONTH_DAY = "MD";
1174
* Type constant used for renderers to represent a weekday
1175
* @property YAHOO.widget.Calendar.WEEKDAY
1180
Calendar.WEEKDAY = "WD";
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
1189
Calendar.RANGE = "R";
1192
* Type constant used for renderers to represent a month across any year
1193
* @property YAHOO.widget.Calendar.MONTH
1198
Calendar.MONTH = "M";
1201
* Constant that represents the total number of date cells that are displayed in a given month
1202
* @property YAHOO.widget.Calendar.DISPLAY_DAYS
1207
Calendar.DISPLAY_DAYS = 42;
1210
* Constant used for halting the execution of the remainder of the render stack
1211
* @property YAHOO.widget.Calendar.STOP_RENDER
1216
Calendar.STOP_RENDER = "S";
1219
* Constant used to represent short date field string formats (e.g. Tu or Feb)
1220
* @property YAHOO.widget.Calendar.SHORT
1225
Calendar.SHORT = "short";
1228
* Constant used to represent long date field string formats (e.g. Monday or February)
1229
* @property YAHOO.widget.Calendar.LONG
1234
Calendar.LONG = "long";
1237
* Constant used to represent medium date field string formats (e.g. Mon)
1238
* @property YAHOO.widget.Calendar.MEDIUM
1243
Calendar.MEDIUM = "medium";
1246
* Constant used to represent single character date field string formats (e.g. M, T, W)
1247
* @property YAHOO.widget.Calendar.ONE_CHAR
1252
Calendar.ONE_CHAR = "1char";
1255
* The set of default Config property keys and values for the Calendar
1256
* @property YAHOO.widget.Calendar._DEFAULT_CONFIG
1262
Calendar._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},
1305
previousMonth : "Previous Month",
1306
nextMonth : "Next Month",
1309
supercedes : ["close", "title"]
1313
var DEF_CFG = Calendar._DEFAULT_CONFIG;
1316
* The set of Custom Event types supported by the Calendar
1317
* @property YAHOO.widget.Calendar._EVENT_TYPES
1323
Calendar._EVENT_TYPES = {
1324
BEFORE_SELECT : "beforeSelect",
1326
BEFORE_DESELECT : "beforeDeselect",
1327
DESELECT : "deselect",
1328
CHANGE_PAGE : "changePage",
1329
BEFORE_RENDER : "beforeRender",
1331
BEFORE_DESTROY : "beforeDestroy",
1332
DESTROY : "destroy",
1335
BEFORE_HIDE : "beforeHide",
1337
BEFORE_SHOW : "beforeShow",
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"
1348
* The set of default style constants for the Calendar
1349
* @property YAHOO.widget.Calendar._STYLES
1355
Calendar._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",
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"
1390
Calendar.prototype = {
1393
* The configuration object used to set up the calendars various locale and style options.
1396
* @deprecated Configuration properties should be set by calling Calendar.cfg.setProperty.
1402
* The parent CalendarGroup, only to be set explicitly by the parent group
1404
* @type CalendarGroup
1409
* The index of this item in the parent group
1416
* The collection of calendar table cells
1418
* @type HTMLTableCellElement[]
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[])
1430
* The id that uniquely identifies this Calendar.
1437
* The unique id associated with the Calendar's container
1438
* @property containerId
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
1448
oDomContainer : null,
1451
* A Date object representing today's date.
1458
* The list of render functions, along with required parameters, used to render cells.
1459
* @property renderStack
1465
* A copy of the initial render functions created before rendering.
1466
* @property _renderStack
1470
_renderStack : null,
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
1481
* The private list of initially selected dates.
1482
* @property _selectedDates
1486
_selectedDates : null,
1489
* A map of DOM event handlers to attach to cells associated with specific CSS class names
1490
* @property domEventMap
1496
* Protected helper used to parse Calendar constructor/init arguments.
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.
1503
* @method _parseArgs
1504
* @param {Array} Function "arguments" array
1505
* @return {Object} Object with id, container, config properties containing
1506
* the reconciled argument values.
1508
_parseArgs : function(args) {
1510
2.4.0 Constructors signatures
1512
new Calendar(String)
1513
new Calendar(HTMLElement)
1514
new Calendar(String, ConfigObject)
1515
new Calendar(HTMLElement, ConfigObject)
1517
Pre 2.4.0 Constructor signatures
1519
new Calendar(String, String)
1520
new Calendar(String, HTMLElement)
1521
new Calendar(String, String, ConfigObject)
1522
new Calendar(String, HTMLElement, ConfigObject)
1524
var nArgs = {id:null, container:null, config:null};
1526
if (args && args.length && args.length > 0) {
1527
switch (args.length) {
1530
nArgs.container = args[0];
1531
nArgs.config = null;
1534
if (Lang.isObject(args[1]) && !args[1].tagName && !(args[1] instanceof String)) {
1536
nArgs.container = args[0];
1537
nArgs.config = args[1];
1540
nArgs.container = args[1];
1541
nArgs.config = null;
1546
nArgs.container = args[1];
1547
nArgs.config = args[2];
1556
* Initializes the Calendar widget.
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.
1563
init : function(id, container, config) {
1564
// Normalize 2.4.0, pre 2.4.0 args
1565
var nArgs = this._parseArgs(arguments);
1568
container = nArgs.container;
1569
config = nArgs.config;
1571
this.oDomContainer = Dom.get(container);
1573
if (!this.oDomContainer.id) {
1574
this.oDomContainer.id = Dom.generateId();
1577
id = this.oDomContainer.id + "_t";
1581
this.containerId = this.oDomContainer.id;
1585
this.today = new Date();
1586
DateMath.clearTime(this.today);
1589
* The Config object used to hold the configuration variables for the Calendar
1591
* @type YAHOO.util.Config
1593
this.cfg = new YAHOO.util.Config(this);
1596
* The local object which contains the Calendar's options
1603
* The local object which contains the Calendar's locale settings
1611
Dom.addClass(this.oDomContainer, this.Style.CSS_CONTAINER);
1612
Dom.addClass(this.oDomContainer, this.Style.CSS_SINGLE);
1614
this.cellDates = [];
1616
this.renderStack = [];
1617
this._renderStack = [];
1622
this.cfg.applyConfig(config, true);
1625
this.cfg.fireQueue();
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.
1632
* @method configIframe
1634
configIframe : function(type, args, obj) {
1635
var useIframe = args[0];
1638
if (Dom.inDocument(this.oDomContainer)) {
1640
var pos = Dom.getStyle(this.oDomContainer, "position");
1642
if (pos == "absolute" || pos == "relative") {
1644
if (!Dom.inDocument(this.iframe)) {
1645
this.iframe = document.createElement("iframe");
1646
this.iframe.src = "javascript:false;";
1648
Dom.setStyle(this.iframe, "opacity", "0");
1650
if (YAHOO.env.ua.ie && YAHOO.env.ua.ie <= 6) {
1651
Dom.addClass(this.iframe, "fixedsize");
1654
this.oDomContainer.insertBefore(this.iframe, this.oDomContainer.firstChild);
1659
if (this.iframe.parentNode) {
1660
this.iframe.parentNode.removeChild(this.iframe);
1670
* Default handler for the "title" property
1671
* @method configTitle
1673
configTitle : function(type, args, obj) {
1674
var title = args[0];
1676
// "" disables title bar
1678
this.createTitleBar(title);
1680
var close = this.cfg.getProperty(DEF_CFG.CLOSE.key);
1682
this.removeTitleBar();
1684
this.createTitleBar(" ");
1690
* Default handler for the "close" property
1691
* @method configClose
1693
configClose : function(type, args, obj) {
1694
var close = args[0],
1695
title = this.cfg.getProperty(DEF_CFG.TITLE.key);
1699
this.createTitleBar(" ");
1701
this.createCloseButton();
1703
this.removeCloseButton();
1705
this.removeTitleBar();
1711
* Initializes Calendar's built-in CustomEvents
1712
* @method initEvents
1714
initEvents : function() {
1716
var defEvents = Calendar._EVENT_TYPES,
1717
CE = YAHOO.util.CustomEvent,
1718
cal = this; // To help with minification
1721
* Fired before a date selection is made
1722
* @event beforeSelectEvent
1724
cal.beforeSelectEvent = new CE(defEvents.BEFORE_SELECT);
1727
* Fired when a date selection is made
1728
* @event selectEvent
1729
* @param {Array} Array of Date field arrays in the format [YYYY, MM, DD].
1731
cal.selectEvent = new CE(defEvents.SELECT);
1734
* Fired before a date or set of dates is deselected
1735
* @event beforeDeselectEvent
1737
cal.beforeDeselectEvent = new CE(defEvents.BEFORE_DESELECT);
1740
* Fired when a date or set of dates is deselected
1741
* @event deselectEvent
1742
* @param {Array} Array of Date field arrays in the format [YYYY, MM, DD].
1744
cal.deselectEvent = new CE(defEvents.DESELECT);
1747
* Fired when the Calendar page is changed
1748
* @event changePageEvent
1750
cal.changePageEvent = new CE(defEvents.CHANGE_PAGE);
1753
* Fired before the Calendar is rendered
1754
* @event beforeRenderEvent
1756
cal.beforeRenderEvent = new CE(defEvents.BEFORE_RENDER);
1759
* Fired when the Calendar is rendered
1760
* @event renderEvent
1762
cal.renderEvent = new CE(defEvents.RENDER);
1765
* Fired just before the Calendar is to be destroyed
1766
* @event beforeDestroyEvent
1768
cal.beforeDestroyEvent = new CE(defEvents.BEFORE_DESTROY);
1771
* Fired after the Calendar is destroyed. This event should be used
1772
* for notification only. When this event is fired, important Calendar instance
1773
* properties, dom references and event listeners have already been
1774
* removed/dereferenced, and hence the Calendar instance is not in a usable
1777
* @event destroyEvent
1779
cal.destroyEvent = new CE(defEvents.DESTROY);
1782
* Fired when the Calendar is reset
1785
cal.resetEvent = new CE(defEvents.RESET);
1788
* Fired when the Calendar is cleared
1791
cal.clearEvent = new CE(defEvents.CLEAR);
1794
* Fired just before the Calendar is to be shown
1795
* @event beforeShowEvent
1797
cal.beforeShowEvent = new CE(defEvents.BEFORE_SHOW);
1800
* Fired after the Calendar is shown
1803
cal.showEvent = new CE(defEvents.SHOW);
1806
* Fired just before the Calendar is to be hidden
1807
* @event beforeHideEvent
1809
cal.beforeHideEvent = new CE(defEvents.BEFORE_HIDE);
1812
* Fired after the Calendar is hidden
1815
cal.hideEvent = new CE(defEvents.HIDE);
1818
* Fired just before the CalendarNavigator is to be shown
1819
* @event beforeShowNavEvent
1821
cal.beforeShowNavEvent = new CE(defEvents.BEFORE_SHOW_NAV);
1824
* Fired after the CalendarNavigator is shown
1825
* @event showNavEvent
1827
cal.showNavEvent = new CE(defEvents.SHOW_NAV);
1830
* Fired just before the CalendarNavigator is to be hidden
1831
* @event beforeHideNavEvent
1833
cal.beforeHideNavEvent = new CE(defEvents.BEFORE_HIDE_NAV);
1836
* Fired after the CalendarNavigator is hidden
1837
* @event hideNavEvent
1839
cal.hideNavEvent = new CE(defEvents.HIDE_NAV);
1842
* Fired just before the CalendarNavigator is to be rendered
1843
* @event beforeRenderNavEvent
1845
cal.beforeRenderNavEvent = new CE(defEvents.BEFORE_RENDER_NAV);
1848
* Fired after the CalendarNavigator is rendered
1849
* @event renderNavEvent
1851
cal.renderNavEvent = new CE(defEvents.RENDER_NAV);
1853
cal.beforeSelectEvent.subscribe(cal.onBeforeSelect, this, true);
1854
cal.selectEvent.subscribe(cal.onSelect, this, true);
1855
cal.beforeDeselectEvent.subscribe(cal.onBeforeDeselect, this, true);
1856
cal.deselectEvent.subscribe(cal.onDeselect, this, true);
1857
cal.changePageEvent.subscribe(cal.onChangePage, this, true);
1858
cal.renderEvent.subscribe(cal.onRender, this, true);
1859
cal.resetEvent.subscribe(cal.onReset, this, true);
1860
cal.clearEvent.subscribe(cal.onClear, this, true);
1864
* The default event handler for clicks on the "Previous Month" navigation UI
1866
* @method doPreviousMonthNav
1867
* @param {DOMEvent} e The DOM event
1868
* @param {Calendar} cal A reference to the calendar
1870
doPreviousMonthNav : function(e, cal) {
1871
Event.preventDefault(e);
1872
// previousMonth invoked in a timeout, to allow
1873
// event to bubble up, with correct target. Calling
1874
// previousMonth, will call render which will remove
1875
// HTML which generated the event, resulting in an
1876
// invalid event target in certain browsers.
1877
setTimeout(function() {
1878
cal.previousMonth();
1879
var navs = Dom.getElementsByClassName(cal.Style.CSS_NAV_LEFT, "a", cal.oDomContainer);
1880
if (navs && navs[0]) {
1891
* The default event handler for clicks on the "Next Month" navigation UI
1893
* @method doNextMonthNav
1894
* @param {DOMEvent} e The DOM event
1895
* @param {Calendar} cal A reference to the calendar
1897
doNextMonthNav : function(e, cal) {
1898
Event.preventDefault(e);
1899
setTimeout(function() {
1901
var navs = Dom.getElementsByClassName(cal.Style.CSS_NAV_RIGHT, "a", cal.oDomContainer);
1902
if (navs && navs[0]) {
1913
* The default event handler for date cell selection. Currently attached to
1914
* the Calendar's bounding box, referenced by it's <a href="#property_oDomContainer">oDomContainer</a> property.
1916
* @method doSelectCell
1917
* @param {DOMEvent} e The DOM event
1918
* @param {Calendar} cal A reference to the calendar
1920
doSelectCell : function(e, cal) {
1921
var cell, d, date, index;
1923
var target = Event.getTarget(e),
1924
tagName = target.tagName.toLowerCase(),
1925
defSelector = false;
1927
while (tagName != "td" && !Dom.hasClass(target, cal.Style.CSS_CELL_SELECTABLE)) {
1929
if (!defSelector && tagName == "a" && Dom.hasClass(target, cal.Style.CSS_CELL_SELECTOR)) {
1933
target = target.parentNode;
1934
tagName = target.tagName.toLowerCase();
1936
if (target == this.oDomContainer || tagName == "html") {
1942
// Stop link href navigation for default renderer
1943
Event.preventDefault(e);
1948
if (Dom.hasClass(cell, cal.Style.CSS_CELL_SELECTABLE)) {
1949
index = cal.getIndexFromId(cell.id);
1951
d = cal.cellDates[index];
1953
date = DateMath.getDate(d[0],d[1]-1,d[2]);
1957
if (cal.Options.MULTI_SELECT) {
1958
link = cell.getElementsByTagName("a")[0];
1963
var cellDate = cal.cellDates[index];
1964
var cellDateIndex = cal._indexOfSelectedFieldArray(cellDate);
1966
if (cellDateIndex > -1) {
1967
cal.deselectCell(index);
1969
cal.selectCell(index);
1973
link = cell.getElementsByTagName("a")[0];
1977
cal.selectCell(index);
1985
* The event that is executed when the user hovers over a cell
1986
* @method doCellMouseOver
1987
* @param {DOMEvent} e The event
1988
* @param {Calendar} cal A reference to the calendar passed by the Event utility
1990
doCellMouseOver : function(e, cal) {
1993
target = Event.getTarget(e);
1998
while (target.tagName && target.tagName.toLowerCase() != "td") {
1999
target = target.parentNode;
2000
if (!target.tagName || target.tagName.toLowerCase() == "html") {
2005
if (Dom.hasClass(target, cal.Style.CSS_CELL_SELECTABLE)) {
2006
Dom.addClass(target, cal.Style.CSS_CELL_HOVER);
2011
* The event that is executed when the user moves the mouse out of a cell
2012
* @method doCellMouseOut
2013
* @param {DOMEvent} e The event
2014
* @param {Calendar} cal A reference to the calendar passed by the Event utility
2016
doCellMouseOut : function(e, cal) {
2019
target = Event.getTarget(e);
2024
while (target.tagName && target.tagName.toLowerCase() != "td") {
2025
target = target.parentNode;
2026
if (!target.tagName || target.tagName.toLowerCase() == "html") {
2031
if (Dom.hasClass(target, cal.Style.CSS_CELL_SELECTABLE)) {
2032
Dom.removeClass(target, cal.Style.CSS_CELL_HOVER);
2036
setupConfig : function() {
2040
* The month/year representing the current visible Calendar date (mm/yyyy)
2042
* @type String | Date
2043
* @default today's date
2045
cfg.addProperty(DEF_CFG.PAGEDATE.key, { value:new Date(), handler:this.configPageDate } );
2048
* The date or range of dates representing the current Calendar selection
2053
cfg.addProperty(DEF_CFG.SELECTED.key, { value:[], handler:this.configSelected } );
2056
* The title to display above the Calendar's month header
2061
cfg.addProperty(DEF_CFG.TITLE.key, { value:DEF_CFG.TITLE.value, handler:this.configTitle } );
2064
* Whether or not a close button should be displayed for this Calendar
2069
cfg.addProperty(DEF_CFG.CLOSE.key, { value:DEF_CFG.CLOSE.value, handler:this.configClose } );
2072
* 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.
2073
* This property is enabled by default for IE6 and below. It is disabled by default for other browsers for performance reasons, but can be
2074
* enabled if required.
2078
* @default true for IE6 and below, false for all other browsers
2080
cfg.addProperty(DEF_CFG.IFRAME.key, { value:DEF_CFG.IFRAME.value, handler:this.configIframe, validator:cfg.checkBoolean } );
2083
* The minimum selectable date in the current Calendar (mm/dd/yyyy)
2085
* @type String | Date
2088
cfg.addProperty(DEF_CFG.MINDATE.key, { value:DEF_CFG.MINDATE.value, handler:this.configMinDate } );
2091
* The maximum selectable date in the current Calendar (mm/dd/yyyy)
2093
* @type String | Date
2096
cfg.addProperty(DEF_CFG.MAXDATE.key, { value:DEF_CFG.MAXDATE.value, handler:this.configMaxDate } );
2099
// Options properties
2102
* True if the Calendar should allow multiple selections. False by default.
2103
* @config MULTI_SELECT
2107
cfg.addProperty(DEF_CFG.MULTI_SELECT.key, { value:DEF_CFG.MULTI_SELECT.value, handler:this.configOptions, validator:cfg.checkBoolean } );
2110
* The weekday the week begins on. Default is 0 (Sunday = 0, Monday = 1 ... Saturday = 6).
2111
* @config START_WEEKDAY
2115
cfg.addProperty(DEF_CFG.START_WEEKDAY.key, { value:DEF_CFG.START_WEEKDAY.value, handler:this.configOptions, validator:cfg.checkNumber } );
2118
* True if the Calendar should show weekday labels. True by default.
2119
* @config SHOW_WEEKDAYS
2123
cfg.addProperty(DEF_CFG.SHOW_WEEKDAYS.key, { value:DEF_CFG.SHOW_WEEKDAYS.value, handler:this.configOptions, validator:cfg.checkBoolean } );
2126
* True if the Calendar should show week row headers. False by default.
2127
* @config SHOW_WEEK_HEADER
2131
cfg.addProperty(DEF_CFG.SHOW_WEEK_HEADER.key, { value:DEF_CFG.SHOW_WEEK_HEADER.value, handler:this.configOptions, validator:cfg.checkBoolean } );
2134
* True if the Calendar should show week row footers. False by default.
2135
* @config SHOW_WEEK_FOOTER
2139
cfg.addProperty(DEF_CFG.SHOW_WEEK_FOOTER.key,{ value:DEF_CFG.SHOW_WEEK_FOOTER.value, handler:this.configOptions, validator:cfg.checkBoolean } );
2142
* True if the Calendar should suppress weeks that are not a part of the current month. False by default.
2143
* @config HIDE_BLANK_WEEKS
2147
cfg.addProperty(DEF_CFG.HIDE_BLANK_WEEKS.key, { value:DEF_CFG.HIDE_BLANK_WEEKS.value, handler:this.configOptions, validator:cfg.checkBoolean } );
2150
* The image that should be used for the left navigation arrow.
2151
* @config NAV_ARROW_LEFT
2153
* @deprecated You can customize the image by overriding the default CSS class for the left arrow - "calnavleft"
2156
cfg.addProperty(DEF_CFG.NAV_ARROW_LEFT.key, { value:DEF_CFG.NAV_ARROW_LEFT.value, handler:this.configOptions } );
2159
* The image that should be used for the right navigation arrow.
2160
* @config NAV_ARROW_RIGHT
2162
* @deprecated You can customize the image by overriding the default CSS class for the right arrow - "calnavright"
2165
cfg.addProperty(DEF_CFG.NAV_ARROW_RIGHT.key, { value:DEF_CFG.NAV_ARROW_RIGHT.value, handler:this.configOptions } );
2167
// Locale properties
2170
* The short month labels for the current locale.
2171
* @config MONTHS_SHORT
2173
* @default ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
2175
cfg.addProperty(DEF_CFG.MONTHS_SHORT.key, { value:DEF_CFG.MONTHS_SHORT.value, handler:this.configLocale } );
2178
* The long month labels for the current locale.
2179
* @config MONTHS_LONG
2181
* @default ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
2183
cfg.addProperty(DEF_CFG.MONTHS_LONG.key, { value:DEF_CFG.MONTHS_LONG.value, handler:this.configLocale } );
2186
* The 1-character weekday labels for the current locale.
2187
* @config WEEKDAYS_1CHAR
2189
* @default ["S", "M", "T", "W", "T", "F", "S"]
2191
cfg.addProperty(DEF_CFG.WEEKDAYS_1CHAR.key, { value:DEF_CFG.WEEKDAYS_1CHAR.value, handler:this.configLocale } );
2194
* The short weekday labels for the current locale.
2195
* @config WEEKDAYS_SHORT
2197
* @default ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]
2199
cfg.addProperty(DEF_CFG.WEEKDAYS_SHORT.key, { value:DEF_CFG.WEEKDAYS_SHORT.value, handler:this.configLocale } );
2202
* The medium weekday labels for the current locale.
2203
* @config WEEKDAYS_MEDIUM
2205
* @default ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
2207
cfg.addProperty(DEF_CFG.WEEKDAYS_MEDIUM.key, { value:DEF_CFG.WEEKDAYS_MEDIUM.value, handler:this.configLocale } );
2210
* The long weekday labels for the current locale.
2211
* @config WEEKDAYS_LONG
2213
* @default ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
2215
cfg.addProperty(DEF_CFG.WEEKDAYS_LONG.key, { value:DEF_CFG.WEEKDAYS_LONG.value, handler:this.configLocale } );
2218
* Refreshes the locale values used to build the Calendar.
2219
* @method refreshLocale
2222
var refreshLocale = function() {
2223
cfg.refireEvent(DEF_CFG.LOCALE_MONTHS.key);
2224
cfg.refireEvent(DEF_CFG.LOCALE_WEEKDAYS.key);
2227
cfg.subscribeToConfigEvent(DEF_CFG.START_WEEKDAY.key, refreshLocale, this, true);
2228
cfg.subscribeToConfigEvent(DEF_CFG.MONTHS_SHORT.key, refreshLocale, this, true);
2229
cfg.subscribeToConfigEvent(DEF_CFG.MONTHS_LONG.key, refreshLocale, this, true);
2230
cfg.subscribeToConfigEvent(DEF_CFG.WEEKDAYS_1CHAR.key, refreshLocale, this, true);
2231
cfg.subscribeToConfigEvent(DEF_CFG.WEEKDAYS_SHORT.key, refreshLocale, this, true);
2232
cfg.subscribeToConfigEvent(DEF_CFG.WEEKDAYS_MEDIUM.key, refreshLocale, this, true);
2233
cfg.subscribeToConfigEvent(DEF_CFG.WEEKDAYS_LONG.key, refreshLocale, this, true);
2236
* The setting that determines which length of month labels should be used. Possible values are "short" and "long".
2237
* @config LOCALE_MONTHS
2241
cfg.addProperty(DEF_CFG.LOCALE_MONTHS.key, { value:DEF_CFG.LOCALE_MONTHS.value, handler:this.configLocaleValues } );
2244
* The setting that determines which length of weekday labels should be used. Possible values are "1char", "short", "medium", and "long".
2245
* @config LOCALE_WEEKDAYS
2249
cfg.addProperty(DEF_CFG.LOCALE_WEEKDAYS.key, { value:DEF_CFG.LOCALE_WEEKDAYS.value, handler:this.configLocaleValues } );
2252
* The value used to delimit individual dates in a date string passed to various Calendar functions.
2253
* @config DATE_DELIMITER
2257
cfg.addProperty(DEF_CFG.DATE_DELIMITER.key, { value:DEF_CFG.DATE_DELIMITER.value, handler:this.configLocale } );
2260
* The value used to delimit date fields in a date string passed to various Calendar functions.
2261
* @config DATE_FIELD_DELIMITER
2265
cfg.addProperty(DEF_CFG.DATE_FIELD_DELIMITER.key, { value:DEF_CFG.DATE_FIELD_DELIMITER.value, handler:this.configLocale } );
2268
* The value used to delimit date ranges in a date string passed to various Calendar functions.
2269
* @config DATE_RANGE_DELIMITER
2273
cfg.addProperty(DEF_CFG.DATE_RANGE_DELIMITER.key, { value:DEF_CFG.DATE_RANGE_DELIMITER.value, handler:this.configLocale } );
2276
* The position of the month in a month/year date string
2277
* @config MY_MONTH_POSITION
2281
cfg.addProperty(DEF_CFG.MY_MONTH_POSITION.key, { value:DEF_CFG.MY_MONTH_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } );
2284
* The position of the year in a month/year date string
2285
* @config MY_YEAR_POSITION
2289
cfg.addProperty(DEF_CFG.MY_YEAR_POSITION.key, { value:DEF_CFG.MY_YEAR_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } );
2292
* The position of the month in a month/day date string
2293
* @config MD_MONTH_POSITION
2297
cfg.addProperty(DEF_CFG.MD_MONTH_POSITION.key, { value:DEF_CFG.MD_MONTH_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } );
2300
* The position of the day in a month/year date string
2301
* @config MD_DAY_POSITION
2305
cfg.addProperty(DEF_CFG.MD_DAY_POSITION.key, { value:DEF_CFG.MD_DAY_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } );
2308
* The position of the month in a month/day/year date string
2309
* @config MDY_MONTH_POSITION
2313
cfg.addProperty(DEF_CFG.MDY_MONTH_POSITION.key, { value:DEF_CFG.MDY_MONTH_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } );
2316
* The position of the day in a month/day/year date string
2317
* @config MDY_DAY_POSITION
2321
cfg.addProperty(DEF_CFG.MDY_DAY_POSITION.key, { value:DEF_CFG.MDY_DAY_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } );
2324
* The position of the year in a month/day/year date string
2325
* @config MDY_YEAR_POSITION
2329
cfg.addProperty(DEF_CFG.MDY_YEAR_POSITION.key, { value:DEF_CFG.MDY_YEAR_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } );
2332
* The position of the month in the month year label string used as the Calendar header
2333
* @config MY_LABEL_MONTH_POSITION
2337
cfg.addProperty(DEF_CFG.MY_LABEL_MONTH_POSITION.key, { value:DEF_CFG.MY_LABEL_MONTH_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } );
2340
* The position of the year in the month year label string used as the Calendar header
2341
* @config MY_LABEL_YEAR_POSITION
2345
cfg.addProperty(DEF_CFG.MY_LABEL_YEAR_POSITION.key, { value:DEF_CFG.MY_LABEL_YEAR_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } );
2348
* The suffix used after the month when rendering the Calendar header
2349
* @config MY_LABEL_MONTH_SUFFIX
2353
cfg.addProperty(DEF_CFG.MY_LABEL_MONTH_SUFFIX.key, { value:DEF_CFG.MY_LABEL_MONTH_SUFFIX.value, handler:this.configLocale } );
2356
* The suffix used after the year when rendering the Calendar header
2357
* @config MY_LABEL_YEAR_SUFFIX
2361
cfg.addProperty(DEF_CFG.MY_LABEL_YEAR_SUFFIX.key, { value:DEF_CFG.MY_LABEL_YEAR_SUFFIX.value, handler:this.configLocale } );
2364
* Configuration for the Month/Year CalendarNavigator UI which allows the user to jump directly to a
2365
* specific Month/Year without having to scroll sequentially through months.
2367
* Setting this property to null (default value) or false, will disable the CalendarNavigator UI.
2370
* Setting this property to true will enable the CalendarNavigatior UI with the default CalendarNavigator configuration values.
2373
* This property can also be set to an object literal containing configuration properties for the CalendarNavigator UI.
2374
* The configuration object expects the the following case-sensitive properties, with the "strings" property being a nested object.
2375
* Any properties which are not provided will use the default values (defined in the CalendarNavigator class).
2379
* <dd><em>Object</em> : An object with the properties shown below, defining the string labels to use in the Navigator's UI
2381
* <dt>month</dt><dd><em>String</em> : The string to use for the month label. Defaults to "Month".</dd>
2382
* <dt>year</dt><dd><em>String</em> : The string to use for the year label. Defaults to "Year".</dd>
2383
* <dt>submit</dt><dd><em>String</em> : The string to use for the submit button label. Defaults to "Okay".</dd>
2384
* <dt>cancel</dt><dd><em>String</em> : The string to use for the cancel button label. Defaults to "Cancel".</dd>
2385
* <dt>invalidYear</dt><dd><em>String</em> : The string to use for invalid year values. Defaults to "Year needs to be a number".</dd>
2388
* <dt>monthFormat</dt><dd><em>String</em> : The month format to use. Either YAHOO.widget.Calendar.LONG, or YAHOO.widget.Calendar.SHORT. Defaults to YAHOO.widget.Calendar.LONG</dd>
2389
* <dt>initialFocus</dt><dd><em>String</em> : Either "year" or "month" specifying which input control should get initial focus. Defaults to "year"</dd>
2395
* month:"Calendar Month",
2396
* year:"Calendar Year",
2399
* invalidYear: "Please enter a valid year"
2401
* monthFormat: YAHOO.widget.Calendar.SHORT,
2402
* initialFocus: "month"
2406
* @type {Object|Boolean}
2409
cfg.addProperty(DEF_CFG.NAV.key, { value:DEF_CFG.NAV.value, handler:this.configNavigator } );
2412
* The map of UI strings which the Calendar UI uses.
2416
* @default An object with the properties shown below:
2418
* <dt>previousMonth</dt><dd><em>String</em> : The string to use for the "Previous Month" navigation UI. Defaults to "Previous Month".</dd>
2419
* <dt>nextMonth</dt><dd><em>String</em> : The string to use for the "Next Month" navigation UI. Defaults to "Next Month".</dd>
2420
* <dt>close</dt><dd><em>String</em> : The string to use for the close button label. Defaults to "Close".</dd>
2423
cfg.addProperty(DEF_CFG.STRINGS.key, {
2424
value:DEF_CFG.STRINGS.value,
2425
handler:this.configStrings,
2426
validator: function(val) {
2427
return Lang.isObject(val);
2429
supercedes:DEF_CFG.STRINGS.supercedes
2434
* The default handler for the "strings" property
2435
* @method configStrings
2437
configStrings : function(type, args, obj) {
2438
var val = Lang.merge(DEF_CFG.STRINGS.value, args[0]);
2439
this.cfg.setProperty(DEF_CFG.STRINGS.key, val, true);
2443
* The default handler for the "pagedate" property
2444
* @method configPageDate
2446
configPageDate : function(type, args, obj) {
2447
this.cfg.setProperty(DEF_CFG.PAGEDATE.key, this._parsePageDate(args[0]), true);
2451
* The default handler for the "mindate" property
2452
* @method configMinDate
2454
configMinDate : function(type, args, obj) {
2456
if (Lang.isString(val)) {
2457
val = this._parseDate(val);
2458
this.cfg.setProperty(DEF_CFG.MINDATE.key, DateMath.getDate(val[0],(val[1]-1),val[2]));
2463
* The default handler for the "maxdate" property
2464
* @method configMaxDate
2466
configMaxDate : function(type, args, obj) {
2468
if (Lang.isString(val)) {
2469
val = this._parseDate(val);
2470
this.cfg.setProperty(DEF_CFG.MAXDATE.key, DateMath.getDate(val[0],(val[1]-1),val[2]));
2475
* The default handler for the "selected" property
2476
* @method configSelected
2478
configSelected : function(type, args, obj) {
2479
var selected = args[0],
2480
cfgSelected = DEF_CFG.SELECTED.key;
2483
if (Lang.isString(selected)) {
2484
this.cfg.setProperty(cfgSelected, this._parseDates(selected), true);
2487
if (! this._selectedDates) {
2488
this._selectedDates = this.cfg.getProperty(cfgSelected);
2493
* The default handler for all configuration options properties
2494
* @method configOptions
2496
configOptions : function(type, args, obj) {
2497
this.Options[type.toUpperCase()] = args[0];
2501
* The default handler for all configuration locale properties
2502
* @method configLocale
2504
configLocale : function(type, args, obj) {
2505
this.Locale[type.toUpperCase()] = args[0];
2507
this.cfg.refireEvent(DEF_CFG.LOCALE_MONTHS.key);
2508
this.cfg.refireEvent(DEF_CFG.LOCALE_WEEKDAYS.key);
2512
* The default handler for all configuration locale field length properties
2513
* @method configLocaleValues
2515
configLocaleValues : function(type, args, obj) {
2517
type = type.toLowerCase();
2521
Locale = this.Locale;
2524
case DEF_CFG.LOCALE_MONTHS.key:
2526
case Calendar.SHORT:
2527
Locale.LOCALE_MONTHS = cfg.getProperty(DEF_CFG.MONTHS_SHORT.key).concat();
2530
Locale.LOCALE_MONTHS = cfg.getProperty(DEF_CFG.MONTHS_LONG.key).concat();
2534
case DEF_CFG.LOCALE_WEEKDAYS.key:
2536
case Calendar.ONE_CHAR:
2537
Locale.LOCALE_WEEKDAYS = cfg.getProperty(DEF_CFG.WEEKDAYS_1CHAR.key).concat();
2539
case Calendar.SHORT:
2540
Locale.LOCALE_WEEKDAYS = cfg.getProperty(DEF_CFG.WEEKDAYS_SHORT.key).concat();
2542
case Calendar.MEDIUM:
2543
Locale.LOCALE_WEEKDAYS = cfg.getProperty(DEF_CFG.WEEKDAYS_MEDIUM.key).concat();
2546
Locale.LOCALE_WEEKDAYS = cfg.getProperty(DEF_CFG.WEEKDAYS_LONG.key).concat();
2550
var START_WEEKDAY = cfg.getProperty(DEF_CFG.START_WEEKDAY.key);
2552
if (START_WEEKDAY > 0) {
2553
for (var w=0; w < START_WEEKDAY; ++w) {
2554
Locale.LOCALE_WEEKDAYS.push(Locale.LOCALE_WEEKDAYS.shift());
2562
* The default handler for the "navigator" property
2563
* @method configNavigator
2565
configNavigator : function(type, args, obj) {
2567
if (YAHOO.widget.CalendarNavigator && (val === true || Lang.isObject(val))) {
2568
if (!this.oNavigator) {
2569
this.oNavigator = new YAHOO.widget.CalendarNavigator(this);
2570
// Cleanup DOM Refs/Events before innerHTML is removed.
2571
this.beforeRenderEvent.subscribe(function () {
2573
this.oNavigator.erase();
2578
if (this.oNavigator) {
2579
this.oNavigator.destroy();
2580
this.oNavigator = null;
2586
* Defines the style constants for the Calendar
2587
* @method initStyles
2589
initStyles : function() {
2591
var defStyle = Calendar._STYLES;
2595
* @property Style.CSS_ROW_HEADER
2597
CSS_ROW_HEADER: defStyle.CSS_ROW_HEADER,
2599
* @property Style.CSS_ROW_FOOTER
2601
CSS_ROW_FOOTER: defStyle.CSS_ROW_FOOTER,
2603
* @property Style.CSS_CELL
2605
CSS_CELL : defStyle.CSS_CELL,
2607
* @property Style.CSS_CELL_SELECTOR
2609
CSS_CELL_SELECTOR : defStyle.CSS_CELL_SELECTOR,
2611
* @property Style.CSS_CELL_SELECTED
2613
CSS_CELL_SELECTED : defStyle.CSS_CELL_SELECTED,
2615
* @property Style.CSS_CELL_SELECTABLE
2617
CSS_CELL_SELECTABLE : defStyle.CSS_CELL_SELECTABLE,
2619
* @property Style.CSS_CELL_RESTRICTED
2621
CSS_CELL_RESTRICTED : defStyle.CSS_CELL_RESTRICTED,
2623
* @property Style.CSS_CELL_TODAY
2625
CSS_CELL_TODAY : defStyle.CSS_CELL_TODAY,
2627
* @property Style.CSS_CELL_OOM
2629
CSS_CELL_OOM : defStyle.CSS_CELL_OOM,
2631
* @property Style.CSS_CELL_OOB
2633
CSS_CELL_OOB : defStyle.CSS_CELL_OOB,
2635
* @property Style.CSS_HEADER
2637
CSS_HEADER : defStyle.CSS_HEADER,
2639
* @property Style.CSS_HEADER_TEXT
2641
CSS_HEADER_TEXT : defStyle.CSS_HEADER_TEXT,
2643
* @property Style.CSS_BODY
2645
CSS_BODY : defStyle.CSS_BODY,
2647
* @property Style.CSS_WEEKDAY_CELL
2649
CSS_WEEKDAY_CELL : defStyle.CSS_WEEKDAY_CELL,
2651
* @property Style.CSS_WEEKDAY_ROW
2653
CSS_WEEKDAY_ROW : defStyle.CSS_WEEKDAY_ROW,
2655
* @property Style.CSS_FOOTER
2657
CSS_FOOTER : defStyle.CSS_FOOTER,
2659
* @property Style.CSS_CALENDAR
2661
CSS_CALENDAR : defStyle.CSS_CALENDAR,
2663
* @property Style.CSS_SINGLE
2665
CSS_SINGLE : defStyle.CSS_SINGLE,
2667
* @property Style.CSS_CONTAINER
2669
CSS_CONTAINER : defStyle.CSS_CONTAINER,
2671
* @property Style.CSS_NAV_LEFT
2673
CSS_NAV_LEFT : defStyle.CSS_NAV_LEFT,
2675
* @property Style.CSS_NAV_RIGHT
2677
CSS_NAV_RIGHT : defStyle.CSS_NAV_RIGHT,
2679
* @property Style.CSS_NAV
2681
CSS_NAV : defStyle.CSS_NAV,
2683
* @property Style.CSS_CLOSE
2685
CSS_CLOSE : defStyle.CSS_CLOSE,
2687
* @property Style.CSS_CELL_TOP
2689
CSS_CELL_TOP : defStyle.CSS_CELL_TOP,
2691
* @property Style.CSS_CELL_LEFT
2693
CSS_CELL_LEFT : defStyle.CSS_CELL_LEFT,
2695
* @property Style.CSS_CELL_RIGHT
2697
CSS_CELL_RIGHT : defStyle.CSS_CELL_RIGHT,
2699
* @property Style.CSS_CELL_BOTTOM
2701
CSS_CELL_BOTTOM : defStyle.CSS_CELL_BOTTOM,
2703
* @property Style.CSS_CELL_HOVER
2705
CSS_CELL_HOVER : defStyle.CSS_CELL_HOVER,
2707
* @property Style.CSS_CELL_HIGHLIGHT1
2709
CSS_CELL_HIGHLIGHT1 : defStyle.CSS_CELL_HIGHLIGHT1,
2711
* @property Style.CSS_CELL_HIGHLIGHT2
2713
CSS_CELL_HIGHLIGHT2 : defStyle.CSS_CELL_HIGHLIGHT2,
2715
* @property Style.CSS_CELL_HIGHLIGHT3
2717
CSS_CELL_HIGHLIGHT3 : defStyle.CSS_CELL_HIGHLIGHT3,
2719
* @property Style.CSS_CELL_HIGHLIGHT4
2721
CSS_CELL_HIGHLIGHT4 : defStyle.CSS_CELL_HIGHLIGHT4
2726
* Builds the date label that will be displayed in the calendar header or
2727
* footer, depending on configuration.
2728
* @method buildMonthLabel
2729
* @return {String} The formatted calendar month label
2731
buildMonthLabel : function() {
2732
return this._buildMonthLabel(this.cfg.getProperty(DEF_CFG.PAGEDATE.key));
2736
* Helper method, to format a Month Year string, given a JavaScript Date, based on the
2737
* Calendar localization settings
2739
* @method _buildMonthLabel
2741
* @param {Date} date
2742
* @return {String} Formated month, year string
2744
_buildMonthLabel : function(date) {
2745
var monthLabel = this.Locale.LOCALE_MONTHS[date.getMonth()] + this.Locale.MY_LABEL_MONTH_SUFFIX,
2746
yearLabel = date.getFullYear() + this.Locale.MY_LABEL_YEAR_SUFFIX;
2748
if (this.Locale.MY_LABEL_MONTH_POSITION == 2 || this.Locale.MY_LABEL_YEAR_POSITION == 1) {
2749
return yearLabel + monthLabel;
2751
return monthLabel + yearLabel;
2756
* Builds the date digit that will be displayed in calendar cells
2757
* @method buildDayLabel
2758
* @param {Date} workingDate The current working date
2759
* @return {String} The formatted day label
2761
buildDayLabel : function(workingDate) {
2762
return workingDate.getDate();
2766
* Creates the title bar element and adds it to Calendar container DIV
2768
* @method createTitleBar
2769
* @param {String} strTitle The title to display in the title bar
2770
* @return The title bar element
2772
createTitleBar : function(strTitle) {
2773
var tDiv = Dom.getElementsByClassName(YAHOO.widget.CalendarGroup.CSS_2UPTITLE, "div", this.oDomContainer)[0] || document.createElement("div");
2774
tDiv.className = YAHOO.widget.CalendarGroup.CSS_2UPTITLE;
2775
tDiv.innerHTML = strTitle;
2776
this.oDomContainer.insertBefore(tDiv, this.oDomContainer.firstChild);
2778
Dom.addClass(this.oDomContainer, "withtitle");
2784
* Removes the title bar element from the DOM
2786
* @method removeTitleBar
2788
removeTitleBar : function() {
2789
var tDiv = Dom.getElementsByClassName(YAHOO.widget.CalendarGroup.CSS_2UPTITLE, "div", this.oDomContainer)[0] || null;
2791
Event.purgeElement(tDiv);
2792
this.oDomContainer.removeChild(tDiv);
2794
Dom.removeClass(this.oDomContainer, "withtitle");
2798
* Creates the close button HTML element and adds it to Calendar container DIV
2800
* @method createCloseButton
2801
* @return The close HTML element created
2803
createCloseButton : function() {
2804
var cssClose = YAHOO.widget.CalendarGroup.CSS_2UPCLOSE,
2805
DEPR_CLOSE_PATH = "us/my/bn/x_d.gif",
2806
lnk = Dom.getElementsByClassName("link-close", "a", this.oDomContainer)[0],
2807
strings = this.cfg.getProperty(DEF_CFG.STRINGS.key),
2808
closeStr = (strings && strings.close) ? strings.close : "";
2811
lnk = document.createElement("a");
2812
Event.addListener(lnk, "click", function(e, cal) {
2814
Event.preventDefault(e);
2819
lnk.className = "link-close";
2821
if (Calendar.IMG_ROOT !== null) {
2822
var img = Dom.getElementsByClassName(cssClose, "img", lnk)[0] || document.createElement("img");
2823
img.src = Calendar.IMG_ROOT + DEPR_CLOSE_PATH;
2824
img.className = cssClose;
2825
lnk.appendChild(img);
2827
lnk.innerHTML = '<span class="' + cssClose + ' ' + this.Style.CSS_CLOSE + '">' + closeStr + '</span>';
2829
this.oDomContainer.appendChild(lnk);
2835
* Removes the close button HTML element from the DOM
2837
* @method removeCloseButton
2839
removeCloseButton : function() {
2840
var btn = Dom.getElementsByClassName("link-close", "a", this.oDomContainer)[0] || null;
2842
Event.purgeElement(btn);
2843
this.oDomContainer.removeChild(btn);
2848
* Renders the calendar header.
2849
* @method renderHeader
2850
* @param {Array} html The current working HTML array
2851
* @return {Array} The current working HTML array
2853
renderHeader : function(html) {
2857
DEPR_NAV_LEFT = "us/tr/callt.gif",
2858
DEPR_NAV_RIGHT = "us/tr/calrt.gif",
2860
pageDate = cfg.getProperty(DEF_CFG.PAGEDATE.key),
2861
strings= cfg.getProperty(DEF_CFG.STRINGS.key),
2862
prevStr = (strings && strings.previousMonth) ? strings.previousMonth : "",
2863
nextStr = (strings && strings.nextMonth) ? strings.nextMonth : "",
2866
if (cfg.getProperty(DEF_CFG.SHOW_WEEK_HEADER.key)) {
2870
if (cfg.getProperty(DEF_CFG.SHOW_WEEK_FOOTER.key)) {
2874
html[html.length] = "<thead>";
2875
html[html.length] = "<tr>";
2876
html[html.length] = '<th colspan="' + colSpan + '" class="' + this.Style.CSS_HEADER_TEXT + '">';
2877
html[html.length] = '<div class="' + this.Style.CSS_HEADER + '">';
2879
var renderLeft, renderRight = false;
2882
if (this.index === 0) {
2885
if (this.index == (this.parent.cfg.getProperty("pages") -1)) {
2894
monthLabel = this._buildMonthLabel(DateMath.subtract(pageDate, DateMath.MONTH, 1));
2896
var leftArrow = cfg.getProperty(DEF_CFG.NAV_ARROW_LEFT.key);
2897
// 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
2898
if (leftArrow === null && Calendar.IMG_ROOT !== null) {
2899
leftArrow = Calendar.IMG_ROOT + DEPR_NAV_LEFT;
2901
var leftStyle = (leftArrow === null) ? "" : ' style="background-image:url(' + leftArrow + ')"';
2902
html[html.length] = '<a class="' + this.Style.CSS_NAV_LEFT + '"' + leftStyle + ' href="#">' + prevStr + ' (' + monthLabel + ')' + '</a>';
2905
var lbl = this.buildMonthLabel();
2906
var cal = this.parent || this;
2907
if (cal.cfg.getProperty("navigator")) {
2908
lbl = "<a class=\"" + this.Style.CSS_NAV + "\" href=\"#\">" + lbl + "</a>";
2910
html[html.length] = lbl;
2913
monthLabel = this._buildMonthLabel(DateMath.add(pageDate, DateMath.MONTH, 1));
2915
var rightArrow = cfg.getProperty(DEF_CFG.NAV_ARROW_RIGHT.key);
2916
if (rightArrow === null && Calendar.IMG_ROOT !== null) {
2917
rightArrow = Calendar.IMG_ROOT + DEPR_NAV_RIGHT;
2919
var rightStyle = (rightArrow === null) ? "" : ' style="background-image:url(' + rightArrow + ')"';
2920
html[html.length] = '<a class="' + this.Style.CSS_NAV_RIGHT + '"' + rightStyle + ' href="#">' + nextStr + ' (' + monthLabel + ')' + '</a>';
2923
html[html.length] = '</div>\n</th>\n</tr>';
2925
if (cfg.getProperty(DEF_CFG.SHOW_WEEKDAYS.key)) {
2926
html = this.buildWeekdays(html);
2929
html[html.length] = '</thead>';
2935
* Renders the Calendar's weekday headers.
2936
* @method buildWeekdays
2937
* @param {Array} html The current working HTML array
2938
* @return {Array} The current working HTML array
2940
buildWeekdays : function(html) {
2942
html[html.length] = '<tr class="' + this.Style.CSS_WEEKDAY_ROW + '">';
2944
if (this.cfg.getProperty(DEF_CFG.SHOW_WEEK_HEADER.key)) {
2945
html[html.length] = '<th> </th>';
2948
for(var i=0;i < this.Locale.LOCALE_WEEKDAYS.length; ++i) {
2949
html[html.length] = '<th class="calweekdaycell">' + this.Locale.LOCALE_WEEKDAYS[i] + '</th>';
2952
if (this.cfg.getProperty(DEF_CFG.SHOW_WEEK_FOOTER.key)) {
2953
html[html.length] = '<th> </th>';
2956
html[html.length] = '</tr>';
2962
* Renders the calendar body.
2963
* @method renderBody
2964
* @param {Date} workingDate The current working Date being used for the render process
2965
* @param {Array} html The current working HTML array
2966
* @return {Array} The current working HTML array
2968
renderBody : function(workingDate, html) {
2970
var startDay = this.cfg.getProperty(DEF_CFG.START_WEEKDAY.key);
2972
this.preMonthDays = workingDate.getDay();
2974
this.preMonthDays -= startDay;
2976
if (this.preMonthDays < 0) {
2977
this.preMonthDays += 7;
2980
this.monthDays = DateMath.findMonthEnd(workingDate).getDate();
2981
this.postMonthDays = Calendar.DISPLAY_DAYS-this.preMonthDays-this.monthDays;
2984
workingDate = DateMath.subtract(workingDate, DateMath.DAY, this.preMonthDays);
2989
cellPrefix = "_cell",
2990
workingDayPrefix = "wd",
2996
todayYear = t.getFullYear(),
2997
todayMonth = t.getMonth(),
2998
todayDate = t.getDate(),
2999
useDate = cfg.getProperty(DEF_CFG.PAGEDATE.key),
3000
hideBlankWeeks = cfg.getProperty(DEF_CFG.HIDE_BLANK_WEEKS.key),
3001
showWeekFooter = cfg.getProperty(DEF_CFG.SHOW_WEEK_FOOTER.key),
3002
showWeekHeader = cfg.getProperty(DEF_CFG.SHOW_WEEK_HEADER.key),
3003
mindate = cfg.getProperty(DEF_CFG.MINDATE.key),
3004
maxdate = cfg.getProperty(DEF_CFG.MAXDATE.key);
3007
mindate = DateMath.clearTime(mindate);
3010
maxdate = DateMath.clearTime(maxdate);
3013
html[html.length] = '<tbody class="m' + (useDate.getMonth()+1) + ' ' + this.Style.CSS_BODY + '">';
3016
tempDiv = document.createElement("div"),
3017
cell = document.createElement("td");
3019
tempDiv.appendChild(cell);
3021
var cal = this.parent || this;
3023
for (var r=0;r<6;r++) {
3024
weekNum = DateMath.getWeekNumber(workingDate, startDay);
3025
weekClass = weekPrefix + weekNum;
3027
// Local OOM check for performance, since we already have pagedate
3028
if (r !== 0 && hideBlankWeeks === true && workingDate.getMonth() != useDate.getMonth()) {
3031
html[html.length] = '<tr class="' + weekClass + '">';
3033
if (showWeekHeader) { html = this.renderRowHeader(weekNum, html); }
3035
for (var d=0; d < 7; d++){ // Render actual days
3039
this.clearElement(cell);
3040
cell.className = this.Style.CSS_CELL;
3041
cell.id = this.id + cellPrefix + i;
3043
if (workingDate.getDate() == todayDate &&
3044
workingDate.getMonth() == todayMonth &&
3045
workingDate.getFullYear() == todayYear) {
3046
cellRenderers[cellRenderers.length]=cal.renderCellStyleToday;
3049
var workingArray = [workingDate.getFullYear(),workingDate.getMonth()+1,workingDate.getDate()];
3050
this.cellDates[this.cellDates.length] = workingArray; // Add this date to cellDates
3052
// Local OOM check for performance, since we already have pagedate
3053
if (workingDate.getMonth() != useDate.getMonth()) {
3054
cellRenderers[cellRenderers.length]=cal.renderCellNotThisMonth;
3056
Dom.addClass(cell, workingDayPrefix + workingDate.getDay());
3057
Dom.addClass(cell, dayPrefix + workingDate.getDate());
3059
for (var s=0;s<this.renderStack.length;++s) {
3063
var rArray = this.renderStack[s],
3071
month = rArray[1][1];
3073
year = rArray[1][0];
3075
if (workingDate.getMonth()+1 == month && workingDate.getDate() == day && workingDate.getFullYear() == year) {
3076
renderer = rArray[2];
3077
this.renderStack.splice(s,1);
3080
case Calendar.MONTH_DAY:
3081
month = rArray[1][0];
3084
if (workingDate.getMonth()+1 == month && workingDate.getDate() == day) {
3085
renderer = rArray[2];
3086
this.renderStack.splice(s,1);
3089
case Calendar.RANGE:
3090
var date1 = rArray[1][0],
3091
date2 = rArray[1][1],
3095
d1 = DateMath.getDate(d1year, d1month-1, d1day),
3099
d2 = DateMath.getDate(d2year, d2month-1, d2day);
3101
if (workingDate.getTime() >= d1.getTime() && workingDate.getTime() <= d2.getTime()) {
3102
renderer = rArray[2];
3104
if (workingDate.getTime()==d2.getTime()) {
3105
this.renderStack.splice(s,1);
3109
case Calendar.WEEKDAY:
3110
var weekday = rArray[1][0];
3111
if (workingDate.getDay()+1 == weekday) {
3112
renderer = rArray[2];
3115
case Calendar.MONTH:
3116
month = rArray[1][0];
3117
if (workingDate.getMonth()+1 == month) {
3118
renderer = rArray[2];
3124
cellRenderers[cellRenderers.length]=renderer;
3130
if (this._indexOfSelectedFieldArray(workingArray) > -1) {
3131
cellRenderers[cellRenderers.length]=cal.renderCellStyleSelected;
3134
if ((mindate && (workingDate.getTime() < mindate.getTime())) ||
3135
(maxdate && (workingDate.getTime() > maxdate.getTime()))
3137
cellRenderers[cellRenderers.length]=cal.renderOutOfBoundsDate;
3139
cellRenderers[cellRenderers.length]=cal.styleCellDefault;
3140
cellRenderers[cellRenderers.length]=cal.renderCellDefault;
3143
for (var x=0; x < cellRenderers.length; ++x) {
3144
if (cellRenderers[x].call(cal, workingDate, cell) == Calendar.STOP_RENDER) {
3149
workingDate.setTime(workingDate.getTime() + DateMath.ONE_DAY_MS);
3150
// Just in case we crossed DST/Summertime boundaries
3151
workingDate = DateMath.clearTime(workingDate);
3153
if (i >= 0 && i <= 6) {
3154
Dom.addClass(cell, this.Style.CSS_CELL_TOP);
3156
if ((i % 7) === 0) {
3157
Dom.addClass(cell, this.Style.CSS_CELL_LEFT);
3159
if (((i+1) % 7) === 0) {
3160
Dom.addClass(cell, this.Style.CSS_CELL_RIGHT);
3163
var postDays = this.postMonthDays;
3164
if (hideBlankWeeks && postDays >= 7) {
3165
var blankWeeks = Math.floor(postDays/7);
3166
for (var p=0;p<blankWeeks;++p) {
3171
if (i >= ((this.preMonthDays+postDays+this.monthDays)-7)) {
3172
Dom.addClass(cell, this.Style.CSS_CELL_BOTTOM);
3175
html[html.length] = tempDiv.innerHTML;
3179
if (showWeekFooter) { html = this.renderRowFooter(weekNum, html); }
3181
html[html.length] = '</tr>';
3185
html[html.length] = '</tbody>';
3191
* Renders the calendar footer. In the default implementation, there is
3193
* @method renderFooter
3194
* @param {Array} html The current working HTML array
3195
* @return {Array} The current working HTML array
3197
renderFooter : function(html) { return html; },
3200
* Renders the calendar after it has been configured. The render() method has a specific call chain that will execute
3201
* when the method is called: renderHeader, renderBody, renderFooter.
3202
* Refer to the documentation for those methods for information on
3203
* individual render tasks.
3206
render : function() {
3207
this.beforeRenderEvent.fire();
3209
// Find starting day of the current month
3210
var workingDate = DateMath.findMonthStart(this.cfg.getProperty(DEF_CFG.PAGEDATE.key));
3212
this.resetRenderers();
3213
this.cellDates.length = 0;
3215
Event.purgeElement(this.oDomContainer, true);
3219
html[html.length] = '<table cellSpacing="0" class="' + this.Style.CSS_CALENDAR + ' y' + workingDate.getFullYear() + '" id="' + this.id + '">';
3220
html = this.renderHeader(html);
3221
html = this.renderBody(workingDate, html);
3222
html = this.renderFooter(html);
3223
html[html.length] = '</table>';
3225
this.oDomContainer.innerHTML = html.join("\n");
3227
this.applyListeners();
3228
this.cells = this.oDomContainer.getElementsByTagName("td");
3230
this.cfg.refireEvent(DEF_CFG.TITLE.key);
3231
this.cfg.refireEvent(DEF_CFG.CLOSE.key);
3232
this.cfg.refireEvent(DEF_CFG.IFRAME.key);
3234
this.renderEvent.fire();
3238
* Applies the Calendar's DOM listeners to applicable elements.
3239
* @method applyListeners
3241
applyListeners : function() {
3242
var root = this.oDomContainer,
3243
cal = this.parent || this,
3247
var linkLeft = Dom.getElementsByClassName(this.Style.CSS_NAV_LEFT, anchor, root),
3248
linkRight = Dom.getElementsByClassName(this.Style.CSS_NAV_RIGHT, anchor, root);
3250
if (linkLeft && linkLeft.length > 0) {
3251
this.linkLeft = linkLeft[0];
3252
Event.addListener(this.linkLeft, click, this.doPreviousMonthNav, cal, true);
3255
if (linkRight && linkRight.length > 0) {
3256
this.linkRight = linkRight[0];
3257
Event.addListener(this.linkRight, click, this.doNextMonthNav, cal, true);
3260
if (cal.cfg.getProperty("navigator") !== null) {
3261
this.applyNavListeners();
3264
if (this.domEventMap) {
3266
for (var cls in this.domEventMap) {
3267
if (Lang.hasOwnProperty(this.domEventMap, cls)) {
3268
var items = this.domEventMap[cls];
3270
if (! (items instanceof Array)) {
3274
for (var i=0;i<items.length;i++) {
3275
var item = items[i];
3276
elements = Dom.getElementsByClassName(cls, item.tag, this.oDomContainer);
3278
for (var c=0;c<elements.length;c++) {
3280
Event.addListener(el, item.event, item.handler, item.scope, item.correct );
3287
Event.addListener(this.oDomContainer, "click", this.doSelectCell, this);
3288
Event.addListener(this.oDomContainer, "mouseover", this.doCellMouseOver, this);
3289
Event.addListener(this.oDomContainer, "mouseout", this.doCellMouseOut, this);
3292
applyNavListeners : function() {
3293
var calParent = this.parent || this,
3295
navBtns = Dom.getElementsByClassName(this.Style.CSS_NAV, "a", this.oDomContainer);
3297
if (navBtns.length > 0) {
3299
Event.addListener(navBtns, "click", function (e, obj) {
3300
var target = Event.getTarget(e);
3302
if (this === target || Dom.isAncestor(this, target)) {
3303
Event.preventDefault(e);
3305
var navigator = calParent.oNavigator;
3307
var pgdate = cal.cfg.getProperty("pagedate");
3308
navigator.setYear(pgdate.getFullYear());
3309
navigator.setMonth(pgdate.getMonth());
3317
* Retrieves the Date object for the specified Calendar cell
3318
* @method getDateByCellId
3319
* @param {String} id The id of the cell
3320
* @return {Date} The Date object for the specified Calendar cell
3322
getDateByCellId : function(id) {
3323
var date = this.getDateFieldsByCellId(id);
3324
return (date) ? DateMath.getDate(date[0],date[1]-1,date[2]) : null;
3328
* Retrieves the Date object for the specified Calendar cell
3329
* @method getDateFieldsByCellId
3330
* @param {String} id The id of the cell
3331
* @return {Array} The array of Date fields for the specified Calendar cell
3333
getDateFieldsByCellId : function(id) {
3334
id = this.getIndexFromId(id);
3335
return (id > -1) ? this.cellDates[id] : null;
3339
* Find the Calendar's cell index for a given date.
3340
* If the date is not found, the method returns -1.
3342
* The returned index can be used to lookup the cell HTMLElement
3343
* using the Calendar's cells array or passed to selectCell to select
3347
* See <a href="#cells">cells</a>, <a href="#selectCell">selectCell</a>.
3349
* @method getCellIndex
3350
* @param {Date} date JavaScript Date object, for which to find a cell index.
3351
* @return {Number} The index of the date in Calendars cellDates/cells arrays, or -1 if the date
3352
* is not on the curently rendered Calendar page.
3354
getCellIndex : function(date) {
3357
var m = date.getMonth(),
3358
y = date.getFullYear(),
3360
dates = this.cellDates;
3362
for (var i = 0; i < dates.length; ++i) {
3363
var cellDate = dates[i];
3364
if (cellDate[0] === y && cellDate[1] === m+1 && cellDate[2] === d) {
3374
* Given the id used to mark each Calendar cell, this method
3375
* extracts the index number from the id.
3377
* @param {String} strId The cell id
3378
* @return {Number} The index of the cell, or -1 if id does not contain an index number
3380
getIndexFromId : function(strId) {
3382
li = strId.lastIndexOf("_cell");
3385
idx = parseInt(strId.substring(li + 5), 10);
3391
// BEGIN BUILT-IN TABLE CELL RENDERERS
3394
* Renders a cell that falls before the minimum date or after the maximum date.
3396
* @method renderOutOfBoundsDate
3397
* @param {Date} workingDate The current working Date object being used to generate the calendar
3398
* @param {HTMLTableCellElement} cell The current working cell in the calendar
3399
* @return {String} YAHOO.widget.Calendar.STOP_RENDER if rendering should stop with this style, null or nothing if rendering
3400
* should not be terminated
3402
renderOutOfBoundsDate : function(workingDate, cell) {
3403
Dom.addClass(cell, this.Style.CSS_CELL_OOB);
3404
cell.innerHTML = workingDate.getDate();
3405
return Calendar.STOP_RENDER;
3409
* Renders the row header for a week.
3410
* @method renderRowHeader
3411
* @param {Number} weekNum The week number of the current row
3412
* @param {Array} cell The current working HTML array
3414
renderRowHeader : function(weekNum, html) {
3415
html[html.length] = '<th class="calrowhead">' + weekNum + '</th>';
3420
* Renders the row footer for a week.
3421
* @method renderRowFooter
3422
* @param {Number} weekNum The week number of the current row
3423
* @param {Array} cell The current working HTML array
3425
renderRowFooter : function(weekNum, html) {
3426
html[html.length] = '<th class="calrowfoot">' + weekNum + '</th>';
3431
* Renders a single standard calendar cell in the calendar widget table.
3432
* All logic for determining how a standard default cell will be rendered is
3433
* encapsulated in this method, and must be accounted for when extending the
3435
* @method renderCellDefault
3436
* @param {Date} workingDate The current working Date object being used to generate the calendar
3437
* @param {HTMLTableCellElement} cell The current working cell in the calendar
3439
renderCellDefault : function(workingDate, cell) {
3440
cell.innerHTML = '<a href="#" class="' + this.Style.CSS_CELL_SELECTOR + '">' + this.buildDayLabel(workingDate) + "</a>";
3444
* Styles a selectable cell.
3445
* @method styleCellDefault
3446
* @param {Date} workingDate The current working Date object being used to generate the calendar
3447
* @param {HTMLTableCellElement} cell The current working cell in the calendar
3449
styleCellDefault : function(workingDate, cell) {
3450
Dom.addClass(cell, this.Style.CSS_CELL_SELECTABLE);
3455
* Renders a single standard calendar cell using the CSS hightlight1 style
3456
* @method renderCellStyleHighlight1
3457
* @param {Date} workingDate The current working Date object being used to generate the calendar
3458
* @param {HTMLTableCellElement} cell The current working cell in the calendar
3460
renderCellStyleHighlight1 : function(workingDate, cell) {
3461
Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT1);
3465
* Renders a single standard calendar cell using the CSS hightlight2 style
3466
* @method renderCellStyleHighlight2
3467
* @param {Date} workingDate The current working Date object being used to generate the calendar
3468
* @param {HTMLTableCellElement} cell The current working cell in the calendar
3470
renderCellStyleHighlight2 : function(workingDate, cell) {
3471
Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT2);
3475
* Renders a single standard calendar cell using the CSS hightlight3 style
3476
* @method renderCellStyleHighlight3
3477
* @param {Date} workingDate The current working Date object being used to generate the calendar
3478
* @param {HTMLTableCellElement} cell The current working cell in the calendar
3480
renderCellStyleHighlight3 : function(workingDate, cell) {
3481
Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT3);
3485
* Renders a single standard calendar cell using the CSS hightlight4 style
3486
* @method renderCellStyleHighlight4
3487
* @param {Date} workingDate The current working Date object being used to generate the calendar
3488
* @param {HTMLTableCellElement} cell The current working cell in the calendar
3490
renderCellStyleHighlight4 : function(workingDate, cell) {
3491
Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT4);
3495
* Applies the default style used for rendering today's date to the current calendar cell
3496
* @method renderCellStyleToday
3497
* @param {Date} workingDate The current working Date object being used to generate the calendar
3498
* @param {HTMLTableCellElement} cell The current working cell in the calendar
3500
renderCellStyleToday : function(workingDate, cell) {
3501
Dom.addClass(cell, this.Style.CSS_CELL_TODAY);
3505
* Applies the default style used for rendering selected dates to the current calendar cell
3506
* @method renderCellStyleSelected
3507
* @param {Date} workingDate The current working Date object being used to generate the calendar
3508
* @param {HTMLTableCellElement} cell The current working cell in the calendar
3509
* @return {String} YAHOO.widget.Calendar.STOP_RENDER if rendering should stop with this style, null or nothing if rendering
3510
* should not be terminated
3512
renderCellStyleSelected : function(workingDate, cell) {
3513
Dom.addClass(cell, this.Style.CSS_CELL_SELECTED);
3517
* Applies the default style used for rendering dates that are not a part of the current
3518
* month (preceding or trailing the cells for the current month)
3519
* @method renderCellNotThisMonth
3520
* @param {Date} workingDate The current working Date object being used to generate the calendar
3521
* @param {HTMLTableCellElement} cell The current working cell in the calendar
3522
* @return {String} YAHOO.widget.Calendar.STOP_RENDER if rendering should stop with this style, null or nothing if rendering
3523
* should not be terminated
3525
renderCellNotThisMonth : function(workingDate, cell) {
3526
Dom.addClass(cell, this.Style.CSS_CELL_OOM);
3527
cell.innerHTML=workingDate.getDate();
3528
return Calendar.STOP_RENDER;
3532
* Renders the current calendar cell as a non-selectable "black-out" date using the default
3534
* @method renderBodyCellRestricted
3535
* @param {Date} workingDate The current working Date object being used to generate the calendar
3536
* @param {HTMLTableCellElement} cell The current working cell in the calendar
3537
* @return {String} YAHOO.widget.Calendar.STOP_RENDER if rendering should stop with this style, null or nothing if rendering
3538
* should not be terminated
3540
renderBodyCellRestricted : function(workingDate, cell) {
3541
Dom.addClass(cell, this.Style.CSS_CELL);
3542
Dom.addClass(cell, this.Style.CSS_CELL_RESTRICTED);
3543
cell.innerHTML=workingDate.getDate();
3544
return Calendar.STOP_RENDER;
3547
// END BUILT-IN TABLE CELL RENDERERS
3549
// BEGIN MONTH NAVIGATION METHODS
3552
* Adds the designated number of months to the current calendar month, and sets the current
3553
* calendar page date to the new month.
3555
* @param {Number} count The number of months to add to the current calendar
3557
addMonths : function(count) {
3558
var cfgPageDate = DEF_CFG.PAGEDATE.key;
3559
this.cfg.setProperty(cfgPageDate, DateMath.add(this.cfg.getProperty(cfgPageDate), DateMath.MONTH, count));
3560
this.resetRenderers();
3561
this.changePageEvent.fire();
3565
* Subtracts the designated number of months from the current calendar month, and sets the current
3566
* calendar page date to the new month.
3567
* @method subtractMonths
3568
* @param {Number} count The number of months to subtract from the current calendar
3570
subtractMonths : function(count) {
3571
var cfgPageDate = DEF_CFG.PAGEDATE.key;
3572
this.cfg.setProperty(cfgPageDate, DateMath.subtract(this.cfg.getProperty(cfgPageDate), DateMath.MONTH, count));
3573
this.resetRenderers();
3574
this.changePageEvent.fire();
3578
* Adds the designated number of years to the current calendar, and sets the current
3579
* calendar page date to the new month.
3581
* @param {Number} count The number of years to add to the current calendar
3583
addYears : function(count) {
3584
var cfgPageDate = DEF_CFG.PAGEDATE.key;
3585
this.cfg.setProperty(cfgPageDate, DateMath.add(this.cfg.getProperty(cfgPageDate), DateMath.YEAR, count));
3586
this.resetRenderers();
3587
this.changePageEvent.fire();
3591
* Subtcats the designated number of years from the current calendar, and sets the current
3592
* calendar page date to the new month.
3593
* @method subtractYears
3594
* @param {Number} count The number of years to subtract from the current calendar
3596
subtractYears : function(count) {
3597
var cfgPageDate = DEF_CFG.PAGEDATE.key;
3598
this.cfg.setProperty(cfgPageDate, DateMath.subtract(this.cfg.getProperty(cfgPageDate), DateMath.YEAR, count));
3599
this.resetRenderers();
3600
this.changePageEvent.fire();
3604
* Navigates to the next month page in the calendar widget.
3607
nextMonth : function() {
3612
* Navigates to the previous month page in the calendar widget.
3613
* @method previousMonth
3615
previousMonth : function() {
3616
this.subtractMonths(1);
3620
* Navigates to the next year in the currently selected month in the calendar widget.
3623
nextYear : function() {
3628
* Navigates to the previous year in the currently selected month in the calendar widget.
3629
* @method previousYear
3631
previousYear : function() {
3632
this.subtractYears(1);
3635
// END MONTH NAVIGATION METHODS
3637
// BEGIN SELECTION METHODS
3640
* Resets the calendar widget to the originally selected month and year, and
3641
* sets the calendar to the initial selection(s).
3644
reset : function() {
3645
this.cfg.resetProperty(DEF_CFG.SELECTED.key);
3646
this.cfg.resetProperty(DEF_CFG.PAGEDATE.key);
3647
this.resetEvent.fire();
3651
* Clears the selected dates in the current calendar widget and sets the calendar
3652
* to the current month and year.
3655
clear : function() {
3656
this.cfg.setProperty(DEF_CFG.SELECTED.key, []);
3657
this.cfg.setProperty(DEF_CFG.PAGEDATE.key, new Date(this.today.getTime()));
3658
this.clearEvent.fire();
3662
* Selects a date or a collection of dates on the current calendar. This method, by default,
3663
* does not call the render method explicitly. Once selection has completed, render must be
3664
* called for the changes to be reflected visually.
3666
* Any dates which are OOB (out of bounds, not selectable) will not be selected and the array of
3667
* selected dates passed to the selectEvent will not contain OOB dates.
3669
* If all dates are OOB, the no state change will occur; beforeSelect and select events will not be fired.
3672
* @param {String/Date/Date[]} date The date string of dates to select in the current calendar. Valid formats are
3673
* individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006).
3674
* Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005).
3675
* This method can also take a JavaScript Date object or an array of Date objects.
3676
* @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected.
3678
select : function(date) {
3680
var aToBeSelected = this._toFieldArray(date),
3683
cfgSelected = DEF_CFG.SELECTED.key;
3686
for (var a=0; a < aToBeSelected.length; ++a) {
3687
var toSelect = aToBeSelected[a];
3689
if (!this.isDateOOB(this._toDate(toSelect))) {
3691
if (validDates.length === 0) {
3692
this.beforeSelectEvent.fire();
3693
selected = this.cfg.getProperty(cfgSelected);
3695
validDates.push(toSelect);
3697
if (this._indexOfSelectedFieldArray(toSelect) == -1) {
3698
selected[selected.length] = toSelect;
3704
if (validDates.length > 0) {
3706
this.parent.cfg.setProperty(cfgSelected, selected);
3708
this.cfg.setProperty(cfgSelected, selected);
3710
this.selectEvent.fire(validDates);
3713
return this.getSelectedDates();
3717
* Selects a date on the current calendar by referencing the index of the cell that should be selected.
3718
* This method is used to easily select a single cell (usually with a mouse click) without having to do
3719
* a full render. The selected style is applied to the cell directly.
3721
* If the cell is not marked with the CSS_CELL_SELECTABLE class (as is the case by default for out of month
3722
* or out of bounds cells), it will not be selected and in such a case beforeSelect and select events will not be fired.
3724
* @method selectCell
3725
* @param {Number} cellIndex The index of the cell to select in the current calendar.
3726
* @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected.
3728
selectCell : function(cellIndex) {
3730
var cell = this.cells[cellIndex],
3731
cellDate = this.cellDates[cellIndex],
3732
dCellDate = this._toDate(cellDate),
3733
selectable = Dom.hasClass(cell, this.Style.CSS_CELL_SELECTABLE);
3738
this.beforeSelectEvent.fire();
3740
var cfgSelected = DEF_CFG.SELECTED.key;
3741
var selected = this.cfg.getProperty(cfgSelected);
3743
var selectDate = cellDate.concat();
3745
if (this._indexOfSelectedFieldArray(selectDate) == -1) {
3746
selected[selected.length] = selectDate;
3749
this.parent.cfg.setProperty(cfgSelected, selected);
3751
this.cfg.setProperty(cfgSelected, selected);
3753
this.renderCellStyleSelected(dCellDate,cell);
3754
this.selectEvent.fire([selectDate]);
3756
this.doCellMouseOut.call(cell, null, this);
3759
return this.getSelectedDates();
3763
* Deselects a date or a collection of dates on the current calendar. This method, by default,
3764
* does not call the render method explicitly. Once deselection has completed, render must be
3765
* called for the changes to be reflected visually.
3767
* The method will not attempt to deselect any dates which are OOB (out of bounds, and hence not selectable)
3768
* and the array of deselected dates passed to the deselectEvent will not contain any OOB dates.
3770
* If all dates are OOB, beforeDeselect and deselect events will not be fired.
3773
* @param {String/Date/Date[]} date The date string of dates to deselect in the current calendar. Valid formats are
3774
* individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006).
3775
* Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005).
3776
* This method can also take a JavaScript Date object or an array of Date objects.
3777
* @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected.
3779
deselect : function(date) {
3781
var aToBeDeselected = this._toFieldArray(date),
3784
cfgSelected = DEF_CFG.SELECTED.key;
3787
for (var a=0; a < aToBeDeselected.length; ++a) {
3788
var toDeselect = aToBeDeselected[a];
3790
if (!this.isDateOOB(this._toDate(toDeselect))) {
3792
if (validDates.length === 0) {
3793
this.beforeDeselectEvent.fire();
3794
selected = this.cfg.getProperty(cfgSelected);
3797
validDates.push(toDeselect);
3799
var index = this._indexOfSelectedFieldArray(toDeselect);
3801
selected.splice(index,1);
3807
if (validDates.length > 0) {
3809
this.parent.cfg.setProperty(cfgSelected, selected);
3811
this.cfg.setProperty(cfgSelected, selected);
3813
this.deselectEvent.fire(validDates);
3816
return this.getSelectedDates();
3820
* Deselects a date on the current calendar by referencing the index of the cell that should be deselected.
3821
* This method is used to easily deselect a single cell (usually with a mouse click) without having to do
3822
* a full render. The selected style is removed from the cell directly.
3824
* If the cell is not marked with the CSS_CELL_SELECTABLE class (as is the case by default for out of month
3825
* or out of bounds cells), the method will not attempt to deselect it and in such a case, beforeDeselect and
3826
* deselect events will not be fired.
3828
* @method deselectCell
3829
* @param {Number} cellIndex The index of the cell to deselect in the current calendar.
3830
* @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected.
3832
deselectCell : function(cellIndex) {
3833
var cell = this.cells[cellIndex],
3834
cellDate = this.cellDates[cellIndex],
3835
cellDateIndex = this._indexOfSelectedFieldArray(cellDate);
3837
var selectable = Dom.hasClass(cell, this.Style.CSS_CELL_SELECTABLE);
3841
this.beforeDeselectEvent.fire();
3843
var selected = this.cfg.getProperty(DEF_CFG.SELECTED.key),
3844
dCellDate = this._toDate(cellDate),
3845
selectDate = cellDate.concat();
3847
if (cellDateIndex > -1) {
3848
if (this.cfg.getProperty(DEF_CFG.PAGEDATE.key).getMonth() == dCellDate.getMonth() &&
3849
this.cfg.getProperty(DEF_CFG.PAGEDATE.key).getFullYear() == dCellDate.getFullYear()) {
3850
Dom.removeClass(cell, this.Style.CSS_CELL_SELECTED);
3852
selected.splice(cellDateIndex, 1);
3856
this.parent.cfg.setProperty(DEF_CFG.SELECTED.key, selected);
3858
this.cfg.setProperty(DEF_CFG.SELECTED.key, selected);
3861
this.deselectEvent.fire([selectDate]);
3864
return this.getSelectedDates();
3868
* Deselects all dates on the current calendar.
3869
* @method deselectAll
3870
* @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected.
3871
* Assuming that this function executes properly, the return value should be an empty array.
3872
* However, the empty array is returned for the sake of being able to check the selection status
3875
deselectAll : function() {
3876
this.beforeDeselectEvent.fire();
3878
var cfgSelected = DEF_CFG.SELECTED.key,
3879
selected = this.cfg.getProperty(cfgSelected),
3880
count = selected.length,
3881
sel = selected.concat();
3884
this.parent.cfg.setProperty(cfgSelected, []);
3886
this.cfg.setProperty(cfgSelected, []);
3890
this.deselectEvent.fire(sel);
3893
return this.getSelectedDates();
3896
// END SELECTION METHODS
3898
// BEGIN TYPE CONVERSION METHODS
3901
* Converts a date (either a JavaScript Date object, or a date string) to the internal data structure
3902
* used to represent dates: [[yyyy,mm,dd],[yyyy,mm,dd]].
3903
* @method _toFieldArray
3905
* @param {String/Date/Date[]} date The date string of dates to deselect in the current calendar. Valid formats are
3906
* individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006).
3907
* Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005).
3908
* This method can also take a JavaScript Date object or an array of Date objects.
3909
* @return {Array[](Number[])} Array of date field arrays
3911
_toFieldArray : function(date) {
3912
var returnDate = [];
3914
if (date instanceof Date) {
3915
returnDate = [[date.getFullYear(), date.getMonth()+1, date.getDate()]];
3916
} else if (Lang.isString(date)) {
3917
returnDate = this._parseDates(date);
3918
} else if (Lang.isArray(date)) {
3919
for (var i=0;i<date.length;++i) {
3921
returnDate[returnDate.length] = [d.getFullYear(),d.getMonth()+1,d.getDate()];
3929
* Converts a date field array [yyyy,mm,dd] to a JavaScript Date object. The date field array
3930
* is the format in which dates are as provided as arguments to selectEvent and deselectEvent listeners.
3933
* @param {Number[]} dateFieldArray The date field array to convert to a JavaScript Date.
3934
* @return {Date} JavaScript Date object representing the date field array.
3936
toDate : function(dateFieldArray) {
3937
return this._toDate(dateFieldArray);
3941
* Converts a date field array [yyyy,mm,dd] to a JavaScript Date object.
3944
* @deprecated Made public, toDate
3945
* @param {Number[]} dateFieldArray The date field array to convert to a JavaScript Date.
3946
* @return {Date} JavaScript Date object representing the date field array
3948
_toDate : function(dateFieldArray) {
3949
if (dateFieldArray instanceof Date) {
3950
return dateFieldArray;
3952
return DateMath.getDate(dateFieldArray[0],dateFieldArray[1]-1,dateFieldArray[2]);
3956
// END TYPE CONVERSION METHODS
3958
// BEGIN UTILITY METHODS
3961
* Converts a date field array [yyyy,mm,dd] to a JavaScript Date object.
3962
* @method _fieldArraysAreEqual
3964
* @param {Number[]} array1 The first date field array to compare
3965
* @param {Number[]} array2 The first date field array to compare
3966
* @return {Boolean} The boolean that represents the equality of the two arrays
3968
_fieldArraysAreEqual : function(array1, array2) {
3971
if (array1[0]==array2[0]&&array1[1]==array2[1]&&array1[2]==array2[2]) {
3979
* Gets the index of a date field array [yyyy,mm,dd] in the current list of selected dates.
3980
* @method _indexOfSelectedFieldArray
3982
* @param {Number[]} find The date field array to search for
3983
* @return {Number} The index of the date field array within the collection of selected dates.
3984
* -1 will be returned if the date is not found.
3986
_indexOfSelectedFieldArray : function(find) {
3988
seldates = this.cfg.getProperty(DEF_CFG.SELECTED.key);
3990
for (var s=0;s<seldates.length;++s) {
3991
var sArray = seldates[s];
3992
if (find[0]==sArray[0]&&find[1]==sArray[1]&&find[2]==sArray[2]) {
4002
* Determines whether a given date is OOM (out of month).
4004
* @param {Date} date The JavaScript Date object for which to check the OOM status
4005
* @return {Boolean} true if the date is OOM
4007
isDateOOM : function(date) {
4008
return (date.getMonth() != this.cfg.getProperty(DEF_CFG.PAGEDATE.key).getMonth());
4012
* Determines whether a given date is OOB (out of bounds - less than the mindate or more than the maxdate).
4015
* @param {Date} date The JavaScript Date object for which to check the OOB status
4016
* @return {Boolean} true if the date is OOB
4018
isDateOOB : function(date) {
4019
var minDate = this.cfg.getProperty(DEF_CFG.MINDATE.key),
4020
maxDate = this.cfg.getProperty(DEF_CFG.MAXDATE.key),
4024
minDate = dm.clearTime(minDate);
4027
maxDate = dm.clearTime(maxDate);
4030
var clearedDate = new Date(date.getTime());
4031
clearedDate = dm.clearTime(clearedDate);
4033
return ((minDate && clearedDate.getTime() < minDate.getTime()) || (maxDate && clearedDate.getTime() > maxDate.getTime()));
4037
* Parses a pagedate configuration property value. The value can either be specified as a string of form "mm/yyyy" or a Date object
4038
* 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
4039
* @method _parsePageDate
4041
* @param {Date|String} date Pagedate value which needs to be parsed
4042
* @return {Date} The Date object representing the pagedate
4044
_parsePageDate : function(date) {
4048
if (date instanceof Date) {
4049
parsedDate = DateMath.findMonthStart(date);
4051
var month, year, aMonthYear;
4052
aMonthYear = date.split(this.cfg.getProperty(DEF_CFG.DATE_FIELD_DELIMITER.key));
4053
month = parseInt(aMonthYear[this.cfg.getProperty(DEF_CFG.MY_MONTH_POSITION.key)-1], 10)-1;
4054
year = parseInt(aMonthYear[this.cfg.getProperty(DEF_CFG.MY_YEAR_POSITION.key)-1], 10);
4056
parsedDate = DateMath.getDate(year, month, 1);
4059
parsedDate = DateMath.getDate(this.today.getFullYear(), this.today.getMonth(), 1);
4064
// END UTILITY METHODS
4066
// BEGIN EVENT HANDLERS
4069
* Event executed before a date is selected in the calendar widget.
4070
* @deprecated Event handlers for this event should be susbcribed to beforeSelectEvent.
4072
onBeforeSelect : function() {
4073
if (this.cfg.getProperty(DEF_CFG.MULTI_SELECT.key) === false) {
4075
this.parent.callChildFunction("clearAllBodyCellStyles", this.Style.CSS_CELL_SELECTED);
4076
this.parent.deselectAll();
4078
this.clearAllBodyCellStyles(this.Style.CSS_CELL_SELECTED);
4085
* Event executed when a date is selected in the calendar widget.
4086
* @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] ]
4087
* @deprecated Event handlers for this event should be susbcribed to selectEvent.
4089
onSelect : function(selected) { },
4092
* Event executed before a date is deselected in the calendar widget.
4093
* @deprecated Event handlers for this event should be susbcribed to beforeDeselectEvent.
4095
onBeforeDeselect : function() { },
4098
* Event executed when a date is deselected in the calendar widget.
4099
* @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] ]
4100
* @deprecated Event handlers for this event should be susbcribed to deselectEvent.
4102
onDeselect : function(deselected) { },
4105
* Event executed when the user navigates to a different calendar page.
4106
* @deprecated Event handlers for this event should be susbcribed to changePageEvent.
4108
onChangePage : function() {
4113
* Event executed when the calendar widget is rendered.
4114
* @deprecated Event handlers for this event should be susbcribed to renderEvent.
4116
onRender : function() { },
4119
* Event executed when the calendar widget is reset to its original state.
4120
* @deprecated Event handlers for this event should be susbcribed to resetEvemt.
4122
onReset : function() { this.render(); },
4125
* Event executed when the calendar widget is completely cleared to the current month with no selections.
4126
* @deprecated Event handlers for this event should be susbcribed to clearEvent.
4128
onClear : function() { this.render(); },
4131
* Validates the calendar widget. This method has no default implementation
4132
* and must be extended by subclassing the widget.
4133
* @return Should return true if the widget validates, and false if
4137
validate : function() { return true; },
4139
// END EVENT HANDLERS
4141
// BEGIN DATE PARSE METHODS
4144
* Converts a date string to a date field array
4146
* @param {String} sDate Date string. Valid formats are mm/dd and mm/dd/yyyy.
4147
* @return A date field array representing the string passed to the method
4148
* @type Array[](Number[])
4150
_parseDate : function(sDate) {
4151
var aDate = sDate.split(this.Locale.DATE_FIELD_DELIMITER),
4154
if (aDate.length == 2) {
4155
rArray = [aDate[this.Locale.MD_MONTH_POSITION-1],aDate[this.Locale.MD_DAY_POSITION-1]];
4156
rArray.type = Calendar.MONTH_DAY;
4158
rArray = [aDate[this.Locale.MDY_YEAR_POSITION-1],aDate[this.Locale.MDY_MONTH_POSITION-1],aDate[this.Locale.MDY_DAY_POSITION-1]];
4159
rArray.type = Calendar.DATE;
4162
for (var i=0;i<rArray.length;i++) {
4163
rArray[i] = parseInt(rArray[i], 10);
4170
* Converts a multi or single-date string to an array of date field arrays
4172
* @param {String} sDates Date string with one or more comma-delimited dates. Valid formats are mm/dd, mm/dd/yyyy, mm/dd/yyyy-mm/dd/yyyy
4173
* @return An array of date field arrays
4174
* @type Array[](Number[])
4176
_parseDates : function(sDates) {
4178
aDates = sDates.split(this.Locale.DATE_DELIMITER);
4180
for (var d=0;d<aDates.length;++d) {
4181
var sDate = aDates[d];
4183
if (sDate.indexOf(this.Locale.DATE_RANGE_DELIMITER) != -1) {
4185
var aRange = sDate.split(this.Locale.DATE_RANGE_DELIMITER),
4186
dateStart = this._parseDate(aRange[0]),
4187
dateEnd = this._parseDate(aRange[1]),
4188
fullRange = this._parseRange(dateStart, dateEnd);
4190
aReturn = aReturn.concat(fullRange);
4192
// This is not a range
4193
var aDate = this._parseDate(sDate);
4194
aReturn.push(aDate);
4201
* Converts a date range to the full list of included dates
4203
* @param {Number[]} startDate Date field array representing the first date in the range
4204
* @param {Number[]} endDate Date field array representing the last date in the range
4205
* @return An array of date field arrays
4206
* @type Array[](Number[])
4208
_parseRange : function(startDate, endDate) {
4209
var dCurrent = DateMath.add(DateMath.getDate(startDate[0],startDate[1]-1,startDate[2]),DateMath.DAY,1),
4210
dEnd = DateMath.getDate(endDate[0], endDate[1]-1, endDate[2]),
4213
results.push(startDate);
4214
while (dCurrent.getTime() <= dEnd.getTime()) {
4215
results.push([dCurrent.getFullYear(),dCurrent.getMonth()+1,dCurrent.getDate()]);
4216
dCurrent = DateMath.add(dCurrent,DateMath.DAY,1);
4221
// END DATE PARSE METHODS
4223
// BEGIN RENDERER METHODS
4226
* Resets the render stack of the current calendar to its original pre-render value.
4228
resetRenderers : function() {
4229
this.renderStack = this._renderStack.concat();
4233
* Removes all custom renderers added to the Calendar through the addRenderer, addMonthRenderer and
4234
* addWeekdayRenderer methods. Calendar's render method needs to be called after removing renderers
4235
* to re-render the Calendar without custom renderers applied.
4237
removeRenderers : function() {
4238
this._renderStack = [];
4239
this.renderStack = [];
4243
* Clears the inner HTML, CSS class and style information from the specified cell.
4244
* @method clearElement
4245
* @param {HTMLTableCellElement} cell The cell to clear
4247
clearElement : function(cell) {
4248
cell.innerHTML = " ";
4253
* Adds a renderer to the render stack. The function reference passed to this method will be executed
4254
* when a date cell matches the conditions specified in the date string for this renderer.
4255
* @method addRenderer
4256
* @param {String} sDates A date string to associate with the specified renderer. Valid formats
4257
* include date (12/24/2005), month/day (12/24), and range (12/1/2004-1/1/2005)
4258
* @param {Function} fnRender The function executed to render cells that match the render rules for this renderer.
4260
addRenderer : function(sDates, fnRender) {
4261
var aDates = this._parseDates(sDates);
4262
for (var i=0;i<aDates.length;++i) {
4263
var aDate = aDates[i];
4265
if (aDate.length == 2) { // this is either a range or a month/day combo
4266
if (aDate[0] instanceof Array) { // this is a range
4267
this._addRenderer(Calendar.RANGE,aDate,fnRender);
4268
} else { // this is a month/day combo
4269
this._addRenderer(Calendar.MONTH_DAY,aDate,fnRender);
4271
} else if (aDate.length == 3) {
4272
this._addRenderer(Calendar.DATE,aDate,fnRender);
4278
* The private method used for adding cell renderers to the local render stack.
4279
* This method is called by other methods that set the renderer type prior to the method call.
4280
* @method _addRenderer
4282
* @param {String} type The type string that indicates the type of date renderer being added.
4283
* Values are YAHOO.widget.Calendar.DATE, YAHOO.widget.Calendar.MONTH_DAY, YAHOO.widget.Calendar.WEEKDAY,
4284
* YAHOO.widget.Calendar.RANGE, YAHOO.widget.Calendar.MONTH
4285
* @param {Array} aDates An array of dates used to construct the renderer. The format varies based
4286
* on the renderer type
4287
* @param {Function} fnRender The function executed to render cells that match the render rules for this renderer.
4289
_addRenderer : function(type, aDates, fnRender) {
4290
var add = [type,aDates,fnRender];
4291
this.renderStack.unshift(add);
4292
this._renderStack = this.renderStack.concat();
4296
* Adds a month to the render stack. The function reference passed to this method will be executed
4297
* when a date cell matches the month passed to this method.
4298
* @method addMonthRenderer
4299
* @param {Number} month The month (1-12) to associate with this renderer
4300
* @param {Function} fnRender The function executed to render cells that match the render rules for this renderer.
4302
addMonthRenderer : function(month, fnRender) {
4303
this._addRenderer(Calendar.MONTH,[month],fnRender);
4307
* Adds a weekday to the render stack. The function reference passed to this method will be executed
4308
* when a date cell matches the weekday passed to this method.
4309
* @method addWeekdayRenderer
4310
* @param {Number} weekday The weekday (Sunday = 1, Monday = 2 ... Saturday = 7) to associate with this renderer
4311
* @param {Function} fnRender The function executed to render cells that match the render rules for this renderer.
4313
addWeekdayRenderer : function(weekday, fnRender) {
4314
this._addRenderer(Calendar.WEEKDAY,[weekday],fnRender);
4317
// END RENDERER METHODS
4319
// BEGIN CSS METHODS
4322
* Removes all styles from all body cells in the current calendar table.
4323
* @method clearAllBodyCellStyles
4324
* @param {style} style The CSS class name to remove from all calendar body cells
4326
clearAllBodyCellStyles : function(style) {
4327
for (var c=0;c<this.cells.length;++c) {
4328
Dom.removeClass(this.cells[c],style);
4334
// BEGIN GETTER/SETTER METHODS
4336
* Sets the calendar's month explicitly
4338
* @param {Number} month The numeric month, from 0 (January) to 11 (December)
4340
setMonth : function(month) {
4341
var cfgPageDate = DEF_CFG.PAGEDATE.key,
4342
current = this.cfg.getProperty(cfgPageDate);
4343
current.setMonth(parseInt(month, 10));
4344
this.cfg.setProperty(cfgPageDate, current);
4348
* Sets the calendar's year explicitly.
4350
* @param {Number} year The numeric 4-digit year
4352
setYear : function(year) {
4353
var cfgPageDate = DEF_CFG.PAGEDATE.key,
4354
current = this.cfg.getProperty(cfgPageDate);
4356
current.setFullYear(parseInt(year, 10));
4357
this.cfg.setProperty(cfgPageDate, current);
4361
* Gets the list of currently selected dates from the calendar.
4362
* @method getSelectedDates
4363
* @return {Date[]} An array of currently selected JavaScript Date objects.
4365
getSelectedDates : function() {
4366
var returnDates = [],
4367
selected = this.cfg.getProperty(DEF_CFG.SELECTED.key);
4369
for (var d=0;d<selected.length;++d) {
4370
var dateArray = selected[d];
4372
var date = DateMath.getDate(dateArray[0],dateArray[1]-1,dateArray[2]);
4373
returnDates.push(date);
4376
returnDates.sort( function(a,b) { return a-b; } );
4380
/// END GETTER/SETTER METHODS ///
4383
* Hides the Calendar's outer container from view.
4387
if (this.beforeHideEvent.fire()) {
4388
this.oDomContainer.style.display = "none";
4389
this.hideEvent.fire();
4394
* Shows the Calendar's outer container.
4398
if (this.beforeShowEvent.fire()) {
4399
this.oDomContainer.style.display = "block";
4400
this.showEvent.fire();
4405
* Returns a string representing the current browser.
4406
* @deprecated As of 2.3.0, environment information is available in YAHOO.env.ua
4411
browser : (function() {
4412
var ua = navigator.userAgent.toLowerCase();
4413
if (ua.indexOf('opera')!=-1) { // Opera (check first in case of spoof)
4415
} else if (ua.indexOf('msie 7')!=-1) { // IE7
4417
} else if (ua.indexOf('msie') !=-1) { // IE
4419
} else if (ua.indexOf('safari')!=-1) { // Safari (check before Gecko because it includes "like Gecko")
4421
} else if (ua.indexOf('gecko') != -1) { // Gecko
4428
* Returns a string representation of the object.
4430
* @return {String} A string representation of the Calendar object.
4432
toString : function() {
4433
return "Calendar " + this.id;
4437
* Destroys the Calendar instance. The method will remove references
4438
* to HTML elements, remove any event listeners added by the Calendar,
4439
* and destroy the Config and CalendarNavigator instances it has created.
4443
destroy : function() {
4445
if (this.beforeDestroyEvent.fire()) {
4449
if (cal.navigator) {
4450
cal.navigator.destroy();
4457
// DOM event listeners
4458
Event.purgeElement(cal.oDomContainer, true);
4460
// Generated markup/DOM - Not removing the container DIV since we didn't create it.
4461
Dom.removeClass(cal.oDomContainer, "withtitle");
4462
Dom.removeClass(cal.oDomContainer, cal.Style.CSS_CONTAINER);
4463
Dom.removeClass(cal.oDomContainer, cal.Style.CSS_SINGLE);
4464
cal.oDomContainer.innerHTML = "";
4466
// JS-to-DOM references
4467
cal.oDomContainer = null;
4470
this.destroyEvent.fire();
4475
YAHOO.widget.Calendar = Calendar;
4478
* @namespace YAHOO.widget
4479
* @class Calendar_Core
4480
* @extends YAHOO.widget.Calendar
4481
* @deprecated The old Calendar_Core class is no longer necessary.
4483
YAHOO.widget.Calendar_Core = YAHOO.widget.Calendar;
4485
YAHOO.widget.Cal_Core = YAHOO.widget.Calendar;
4491
var Dom = YAHOO.util.Dom,
4492
DateMath = YAHOO.widget.DateMath,
4493
Event = YAHOO.util.Event,
4495
Calendar = YAHOO.widget.Calendar;
4498
* YAHOO.widget.CalendarGroup is a special container class for YAHOO.widget.Calendar. This class facilitates
4499
* the ability to have multi-page calendar views that share a single dataset and are
4500
* dependent on each other.
4502
* The calendar group instance will refer to each of its elements using a 0-based index.
4503
* For example, to construct the placeholder for a calendar group widget with id "cal1" and
4504
* containerId of "cal1Container", the markup would be as follows:
4506
* <div id="cal1Container_0"></div>
4507
* <div id="cal1Container_1"></div>
4509
* The tables for the calendars ("cal1_0" and "cal1_1") will be inserted into those containers.
4512
* <strong>NOTE: As of 2.4.0, the constructor's ID argument is optional.</strong>
4513
* The CalendarGroup can be constructed by simply providing a container ID string,
4514
* or a reference to a container DIV HTMLElement (the element needs to exist
4519
* var c = new YAHOO.widget.CalendarGroup("calContainer", configOptions);
4523
* var containerDiv = YAHOO.util.Dom.get("calContainer");
4524
* var c = new YAHOO.widget.CalendarGroup(containerDiv, configOptions);
4528
* If not provided, the ID will be generated from the container DIV ID by adding an "_t" suffix.
4529
* For example if an ID is not provided, and the container's ID is "calContainer", the CalendarGroup's ID will be set to "calContainer_t".
4532
* @namespace YAHOO.widget
4533
* @class CalendarGroup
4535
* @param {String} id optional The id of the table element that will represent the CalendarGroup widget. As of 2.4.0, this argument is optional.
4536
* @param {String | HTMLElement} container The id of the container div element that will wrap the CalendarGroup table, or a reference to a DIV element which exists in the document.
4537
* @param {Object} config optional The configuration object containing the initial configuration values for the CalendarGroup.
4539
function CalendarGroup(id, containerId, config) {
4540
if (arguments.length > 0) {
4541
this.init.apply(this, arguments);
4546
* The set of default Config property keys and values for the CalendarGroup
4547
* @property YAHOO.widget.CalendarGroup._DEFAULT_CONFIG
4553
CalendarGroup._DEFAULT_CONFIG = Calendar._DEFAULT_CONFIG;
4554
CalendarGroup._DEFAULT_CONFIG.PAGES = {key:"pages", value:2};
4556
var DEF_CFG = CalendarGroup._DEFAULT_CONFIG;
4558
CalendarGroup.prototype = {
4561
* Initializes the calendar group. All subclasses must call this method in order for the
4562
* group to be initialized properly.
4564
* @param {String} id optional The id of the table element that will represent the CalendarGroup widget. As of 2.4.0, this argument is optional.
4565
* @param {String | HTMLElement} container The id of the container div element that will wrap the CalendarGroup table, or a reference to a DIV element which exists in the document.
4566
* @param {Object} config optional The configuration object containing the initial configuration values for the CalendarGroup.
4568
init : function(id, container, config) {
4570
// Normalize 2.4.0, pre 2.4.0 args
4571
var nArgs = this._parseArgs(arguments);
4574
container = nArgs.container;
4575
config = nArgs.config;
4577
this.oDomContainer = Dom.get(container);
4579
if (!this.oDomContainer.id) {
4580
this.oDomContainer.id = Dom.generateId();
4583
id = this.oDomContainer.id + "_t";
4587
* The unique id associated with the CalendarGroup
4594
* The unique id associated with the CalendarGroup container
4595
* @property containerId
4598
this.containerId = this.oDomContainer.id;
4604
* The collection of Calendar pages contained within the CalendarGroup
4606
* @type YAHOO.widget.Calendar[]
4610
Dom.addClass(this.oDomContainer, CalendarGroup.CSS_CONTAINER);
4611
Dom.addClass(this.oDomContainer, CalendarGroup.CSS_MULTI_UP);
4614
* The Config object used to hold the configuration variables for the CalendarGroup
4616
* @type YAHOO.util.Config
4618
this.cfg = new YAHOO.util.Config(this);
4621
* The local object which contains the CalendarGroup's options
4628
* The local object which contains the CalendarGroup's locale settings
4637
this.cfg.applyConfig(config, true);
4640
this.cfg.fireQueue();
4642
// OPERA HACK FOR MISWRAPPED FLOATS
4643
if (YAHOO.env.ua.opera){
4644
this.renderEvent.subscribe(this._fixWidth, this, true);
4645
this.showEvent.subscribe(this._fixWidth, this, true);
4650
setupConfig : function() {
4655
* The number of pages to include in the CalendarGroup. This value can only be set once, in the CalendarGroup's constructor arguments.
4660
cfg.addProperty(DEF_CFG.PAGES.key, { value:DEF_CFG.PAGES.value, validator:cfg.checkNumber, handler:this.configPages } );
4663
* The month/year representing the current visible Calendar date (mm/yyyy)
4665
* @type String | Date
4666
* @default today's date
4668
cfg.addProperty(DEF_CFG.PAGEDATE.key, { value:new Date(), handler:this.configPageDate } );
4671
* The date or range of dates representing the current Calendar selection
4677
cfg.addProperty(DEF_CFG.SELECTED.key, { value:[], handler:this.configSelected } );
4680
* The title to display above the CalendarGroup's month header
4685
cfg.addProperty(DEF_CFG.TITLE.key, { value:DEF_CFG.TITLE.value, handler:this.configTitle } );
4688
* Whether or not a close button should be displayed for this CalendarGroup
4693
cfg.addProperty(DEF_CFG.CLOSE.key, { value:DEF_CFG.CLOSE.value, handler:this.configClose } );
4696
* 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.
4697
* This property is enabled by default for IE6 and below. It is disabled by default for other browsers for performance reasons, but can be
4698
* enabled if required.
4702
* @default true for IE6 and below, false for all other browsers
4704
cfg.addProperty(DEF_CFG.IFRAME.key, { value:DEF_CFG.IFRAME.value, handler:this.configIframe, validator:cfg.checkBoolean } );
4707
* The minimum selectable date in the current Calendar (mm/dd/yyyy)
4709
* @type String | Date
4712
cfg.addProperty(DEF_CFG.MINDATE.key, { value:DEF_CFG.MINDATE.value, handler:this.delegateConfig } );
4715
* The maximum selectable date in the current Calendar (mm/dd/yyyy)
4717
* @type String | Date
4720
cfg.addProperty(DEF_CFG.MAXDATE.key, { value:DEF_CFG.MAXDATE.value, handler:this.delegateConfig } );
4722
// Options properties
4725
* True if the Calendar should allow multiple selections. False by default.
4726
* @config MULTI_SELECT
4730
cfg.addProperty(DEF_CFG.MULTI_SELECT.key, { value:DEF_CFG.MULTI_SELECT.value, handler:this.delegateConfig, validator:cfg.checkBoolean } );
4733
* The weekday the week begins on. Default is 0 (Sunday).
4734
* @config START_WEEKDAY
4738
cfg.addProperty(DEF_CFG.START_WEEKDAY.key, { value:DEF_CFG.START_WEEKDAY.value, handler:this.delegateConfig, validator:cfg.checkNumber } );
4741
* True if the Calendar should show weekday labels. True by default.
4742
* @config SHOW_WEEKDAYS
4746
cfg.addProperty(DEF_CFG.SHOW_WEEKDAYS.key, { value:DEF_CFG.SHOW_WEEKDAYS.value, handler:this.delegateConfig, validator:cfg.checkBoolean } );
4749
* True if the Calendar should show week row headers. False by default.
4750
* @config SHOW_WEEK_HEADER
4754
cfg.addProperty(DEF_CFG.SHOW_WEEK_HEADER.key,{ value:DEF_CFG.SHOW_WEEK_HEADER.value, handler:this.delegateConfig, validator:cfg.checkBoolean } );
4757
* True if the Calendar should show week row footers. False by default.
4758
* @config SHOW_WEEK_FOOTER
4762
cfg.addProperty(DEF_CFG.SHOW_WEEK_FOOTER.key,{ value:DEF_CFG.SHOW_WEEK_FOOTER.value, handler:this.delegateConfig, validator:cfg.checkBoolean } );
4765
* True if the Calendar should suppress weeks that are not a part of the current month. False by default.
4766
* @config HIDE_BLANK_WEEKS
4770
cfg.addProperty(DEF_CFG.HIDE_BLANK_WEEKS.key,{ value:DEF_CFG.HIDE_BLANK_WEEKS.value, handler:this.delegateConfig, validator:cfg.checkBoolean } );
4773
* The image that should be used for the left navigation arrow.
4774
* @config NAV_ARROW_LEFT
4776
* @deprecated You can customize the image by overriding the default CSS class for the left arrow - "calnavleft"
4779
cfg.addProperty(DEF_CFG.NAV_ARROW_LEFT.key, { value:DEF_CFG.NAV_ARROW_LEFT.value, handler:this.delegateConfig } );
4782
* The image that should be used for the right navigation arrow.
4783
* @config NAV_ARROW_RIGHT
4785
* @deprecated You can customize the image by overriding the default CSS class for the right arrow - "calnavright"
4788
cfg.addProperty(DEF_CFG.NAV_ARROW_RIGHT.key, { value:DEF_CFG.NAV_ARROW_RIGHT.value, handler:this.delegateConfig } );
4790
// Locale properties
4793
* The short month labels for the current locale.
4794
* @config MONTHS_SHORT
4796
* @default ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
4798
cfg.addProperty(DEF_CFG.MONTHS_SHORT.key, { value:DEF_CFG.MONTHS_SHORT.value, handler:this.delegateConfig } );
4801
* The long month labels for the current locale.
4802
* @config MONTHS_LONG
4804
* @default ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
4806
cfg.addProperty(DEF_CFG.MONTHS_LONG.key, { value:DEF_CFG.MONTHS_LONG.value, handler:this.delegateConfig } );
4809
* The 1-character weekday labels for the current locale.
4810
* @config WEEKDAYS_1CHAR
4812
* @default ["S", "M", "T", "W", "T", "F", "S"]
4814
cfg.addProperty(DEF_CFG.WEEKDAYS_1CHAR.key, { value:DEF_CFG.WEEKDAYS_1CHAR.value, handler:this.delegateConfig } );
4817
* The short weekday labels for the current locale.
4818
* @config WEEKDAYS_SHORT
4820
* @default ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]
4822
cfg.addProperty(DEF_CFG.WEEKDAYS_SHORT.key, { value:DEF_CFG.WEEKDAYS_SHORT.value, handler:this.delegateConfig } );
4825
* The medium weekday labels for the current locale.
4826
* @config WEEKDAYS_MEDIUM
4828
* @default ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
4830
cfg.addProperty(DEF_CFG.WEEKDAYS_MEDIUM.key, { value:DEF_CFG.WEEKDAYS_MEDIUM.value, handler:this.delegateConfig } );
4833
* The long weekday labels for the current locale.
4834
* @config WEEKDAYS_LONG
4836
* @default ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
4838
cfg.addProperty(DEF_CFG.WEEKDAYS_LONG.key, { value:DEF_CFG.WEEKDAYS_LONG.value, handler:this.delegateConfig } );
4841
* The setting that determines which length of month labels should be used. Possible values are "short" and "long".
4842
* @config LOCALE_MONTHS
4846
cfg.addProperty(DEF_CFG.LOCALE_MONTHS.key, { value:DEF_CFG.LOCALE_MONTHS.value, handler:this.delegateConfig } );
4849
* The setting that determines which length of weekday labels should be used. Possible values are "1char", "short", "medium", and "long".
4850
* @config LOCALE_WEEKDAYS
4854
cfg.addProperty(DEF_CFG.LOCALE_WEEKDAYS.key, { value:DEF_CFG.LOCALE_WEEKDAYS.value, handler:this.delegateConfig } );
4857
* The value used to delimit individual dates in a date string passed to various Calendar functions.
4858
* @config DATE_DELIMITER
4862
cfg.addProperty(DEF_CFG.DATE_DELIMITER.key, { value:DEF_CFG.DATE_DELIMITER.value, handler:this.delegateConfig } );
4865
* The value used to delimit date fields in a date string passed to various Calendar functions.
4866
* @config DATE_FIELD_DELIMITER
4870
cfg.addProperty(DEF_CFG.DATE_FIELD_DELIMITER.key,{ value:DEF_CFG.DATE_FIELD_DELIMITER.value, handler:this.delegateConfig } );
4873
* The value used to delimit date ranges in a date string passed to various Calendar functions.
4874
* @config DATE_RANGE_DELIMITER
4878
cfg.addProperty(DEF_CFG.DATE_RANGE_DELIMITER.key,{ value:DEF_CFG.DATE_RANGE_DELIMITER.value, handler:this.delegateConfig } );
4881
* The position of the month in a month/year date string
4882
* @config MY_MONTH_POSITION
4886
cfg.addProperty(DEF_CFG.MY_MONTH_POSITION.key, { value:DEF_CFG.MY_MONTH_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );
4889
* The position of the year in a month/year date string
4890
* @config MY_YEAR_POSITION
4894
cfg.addProperty(DEF_CFG.MY_YEAR_POSITION.key, { value:DEF_CFG.MY_YEAR_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );
4897
* The position of the month in a month/day date string
4898
* @config MD_MONTH_POSITION
4902
cfg.addProperty(DEF_CFG.MD_MONTH_POSITION.key, { value:DEF_CFG.MD_MONTH_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );
4905
* The position of the day in a month/year date string
4906
* @config MD_DAY_POSITION
4910
cfg.addProperty(DEF_CFG.MD_DAY_POSITION.key, { value:DEF_CFG.MD_DAY_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );
4913
* The position of the month in a month/day/year date string
4914
* @config MDY_MONTH_POSITION
4918
cfg.addProperty(DEF_CFG.MDY_MONTH_POSITION.key, { value:DEF_CFG.MDY_MONTH_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );
4921
* The position of the day in a month/day/year date string
4922
* @config MDY_DAY_POSITION
4926
cfg.addProperty(DEF_CFG.MDY_DAY_POSITION.key, { value:DEF_CFG.MDY_DAY_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );
4929
* The position of the year in a month/day/year date string
4930
* @config MDY_YEAR_POSITION
4934
cfg.addProperty(DEF_CFG.MDY_YEAR_POSITION.key, { value:DEF_CFG.MDY_YEAR_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );
4937
* The position of the month in the month year label string used as the Calendar header
4938
* @config MY_LABEL_MONTH_POSITION
4942
cfg.addProperty(DEF_CFG.MY_LABEL_MONTH_POSITION.key, { value:DEF_CFG.MY_LABEL_MONTH_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );
4945
* The position of the year in the month year label string used as the Calendar header
4946
* @config MY_LABEL_YEAR_POSITION
4950
cfg.addProperty(DEF_CFG.MY_LABEL_YEAR_POSITION.key, { value:DEF_CFG.MY_LABEL_YEAR_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } );
4953
* The suffix used after the month when rendering the Calendar header
4954
* @config MY_LABEL_MONTH_SUFFIX
4958
cfg.addProperty(DEF_CFG.MY_LABEL_MONTH_SUFFIX.key, { value:DEF_CFG.MY_LABEL_MONTH_SUFFIX.value, handler:this.delegateConfig } );
4961
* The suffix used after the year when rendering the Calendar header
4962
* @config MY_LABEL_YEAR_SUFFIX
4966
cfg.addProperty(DEF_CFG.MY_LABEL_YEAR_SUFFIX.key, { value:DEF_CFG.MY_LABEL_YEAR_SUFFIX.value, handler:this.delegateConfig } );
4969
* Configuration for the Month Year Navigation UI. By default it is disabled
4974
cfg.addProperty(DEF_CFG.NAV.key, { value:DEF_CFG.NAV.value, handler:this.configNavigator } );
4977
* The map of UI strings which the CalendarGroup UI uses.
4981
* @default An object with the properties shown below:
4983
* <dt>previousMonth</dt><dd><em>String</em> : The string to use for the "Previous Month" navigation UI. Defaults to "Previous Month".</dd>
4984
* <dt>nextMonth</dt><dd><em>String</em> : The string to use for the "Next Month" navigation UI. Defaults to "Next Month".</dd>
4985
* <dt>close</dt><dd><em>String</em> : The string to use for the close button label. Defaults to "Close".</dd>
4988
cfg.addProperty(DEF_CFG.STRINGS.key, {
4989
value:DEF_CFG.STRINGS.value,
4990
handler:this.configStrings,
4991
validator: function(val) {
4992
return Lang.isObject(val);
4994
supercedes: DEF_CFG.STRINGS.supercedes
4999
* Initializes CalendarGroup's built-in CustomEvents
5000
* @method initEvents
5002
initEvents : function() {
5006
CE = YAHOO.util.CustomEvent;
5009
* Proxy subscriber to subscribe to the CalendarGroup's child Calendars' CustomEvents
5012
* @param {Function} fn The function to subscribe to this CustomEvent
5013
* @param {Object} obj The CustomEvent's scope object
5014
* @param {Boolean} bOverride Whether or not to apply scope correction
5016
var sub = function(fn, obj, bOverride) {
5017
for (var p=0;p<me.pages.length;++p) {
5018
var cal = me.pages[p];
5019
cal[this.type + strEvent].subscribe(fn, obj, bOverride);
5024
* Proxy unsubscriber to unsubscribe from the CalendarGroup's child Calendars' CustomEvents
5027
* @param {Function} fn The function to subscribe to this CustomEvent
5028
* @param {Object} obj The CustomEvent's scope object
5030
var unsub = function(fn, obj) {
5031
for (var p=0;p<me.pages.length;++p) {
5032
var cal = me.pages[p];
5033
cal[this.type + strEvent].unsubscribe(fn, obj);
5037
var defEvents = Calendar._EVENT_TYPES;
5040
* Fired before a date selection is made
5041
* @event beforeSelectEvent
5043
me.beforeSelectEvent = new CE(defEvents.BEFORE_SELECT);
5044
me.beforeSelectEvent.subscribe = sub; me.beforeSelectEvent.unsubscribe = unsub;
5047
* Fired when a date selection is made
5048
* @event selectEvent
5049
* @param {Array} Array of Date field arrays in the format [YYYY, MM, DD].
5051
me.selectEvent = new CE(defEvents.SELECT);
5052
me.selectEvent.subscribe = sub; me.selectEvent.unsubscribe = unsub;
5055
* Fired before a date or set of dates is deselected
5056
* @event beforeDeselectEvent
5058
me.beforeDeselectEvent = new CE(defEvents.BEFORE_DESELECT);
5059
me.beforeDeselectEvent.subscribe = sub; me.beforeDeselectEvent.unsubscribe = unsub;
5062
* Fired when a date or set of dates has been deselected
5063
* @event deselectEvent
5064
* @param {Array} Array of Date field arrays in the format [YYYY, MM, DD].
5066
me.deselectEvent = new CE(defEvents.DESELECT);
5067
me.deselectEvent.subscribe = sub; me.deselectEvent.unsubscribe = unsub;
5070
* Fired when the Calendar page is changed
5071
* @event changePageEvent
5073
me.changePageEvent = new CE(defEvents.CHANGE_PAGE);
5074
me.changePageEvent.subscribe = sub; me.changePageEvent.unsubscribe = unsub;
5077
* Fired before the Calendar is rendered
5078
* @event beforeRenderEvent
5080
me.beforeRenderEvent = new CE(defEvents.BEFORE_RENDER);
5081
me.beforeRenderEvent.subscribe = sub; me.beforeRenderEvent.unsubscribe = unsub;
5084
* Fired when the Calendar is rendered
5085
* @event renderEvent
5087
me.renderEvent = new CE(defEvents.RENDER);
5088
me.renderEvent.subscribe = sub; me.renderEvent.unsubscribe = unsub;
5091
* Fired when the Calendar is reset
5094
me.resetEvent = new CE(defEvents.RESET);
5095
me.resetEvent.subscribe = sub; me.resetEvent.unsubscribe = unsub;
5098
* Fired when the Calendar is cleared
5101
me.clearEvent = new CE(defEvents.CLEAR);
5102
me.clearEvent.subscribe = sub; me.clearEvent.unsubscribe = unsub;
5105
* Fired just before the CalendarGroup is to be shown
5106
* @event beforeShowEvent
5108
me.beforeShowEvent = new CE(defEvents.BEFORE_SHOW);
5111
* Fired after the CalendarGroup is shown
5114
me.showEvent = new CE(defEvents.SHOW);
5117
* Fired just before the CalendarGroup is to be hidden
5118
* @event beforeHideEvent
5120
me.beforeHideEvent = new CE(defEvents.BEFORE_HIDE);
5123
* Fired after the CalendarGroup is hidden
5126
me.hideEvent = new CE(defEvents.HIDE);
5129
* Fired just before the CalendarNavigator is to be shown
5130
* @event beforeShowNavEvent
5132
me.beforeShowNavEvent = new CE(defEvents.BEFORE_SHOW_NAV);
5135
* Fired after the CalendarNavigator is shown
5136
* @event showNavEvent
5138
me.showNavEvent = new CE(defEvents.SHOW_NAV);
5141
* Fired just before the CalendarNavigator is to be hidden
5142
* @event beforeHideNavEvent
5144
me.beforeHideNavEvent = new CE(defEvents.BEFORE_HIDE_NAV);
5147
* Fired after the CalendarNavigator is hidden
5148
* @event hideNavEvent
5150
me.hideNavEvent = new CE(defEvents.HIDE_NAV);
5153
* Fired just before the CalendarNavigator is to be rendered
5154
* @event beforeRenderNavEvent
5156
me.beforeRenderNavEvent = new CE(defEvents.BEFORE_RENDER_NAV);
5159
* Fired after the CalendarNavigator is rendered
5160
* @event renderNavEvent
5162
me.renderNavEvent = new CE(defEvents.RENDER_NAV);
5165
* Fired just before the CalendarGroup is to be destroyed
5166
* @event beforeDestroyEvent
5168
me.beforeDestroyEvent = new CE(defEvents.BEFORE_DESTROY);
5171
* Fired after the CalendarGroup is destroyed. This event should be used
5172
* for notification only. When this event is fired, important CalendarGroup instance
5173
* properties, dom references and event listeners have already been
5174
* removed/dereferenced, and hence the CalendarGroup instance is not in a usable
5177
* @event destroyEvent
5179
me.destroyEvent = new CE(defEvents.DESTROY);
5183
* The default Config handler for the "pages" property
5184
* @method configPages
5185
* @param {String} type The CustomEvent type (usually the property name)
5186
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
5187
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
5189
configPages : function(type, args, obj) {
5190
var pageCount = args[0],
5191
cfgPageDate = DEF_CFG.PAGEDATE.key,
5194
firstPageDate = null,
5195
groupCalClass = "groupcal",
5196
firstClass = "first-of-type",
5197
lastClass = "last-of-type";
5199
for (var p=0;p<pageCount;++p) {
5200
var calId = this.id + sep + p,
5201
calContainerId = this.containerId + sep + p,
5202
childConfig = this.cfg.getConfig();
5204
childConfig.close = false;
5205
childConfig.title = false;
5206
childConfig.navigator = null;
5209
caldate = new Date(firstPageDate);
5210
this._setMonthOnDate(caldate, caldate.getMonth() + p);
5211
childConfig.pageDate = caldate;
5214
var cal = this.constructChild(calId, calContainerId, childConfig);
5216
Dom.removeClass(cal.oDomContainer, this.Style.CSS_SINGLE);
5217
Dom.addClass(cal.oDomContainer, groupCalClass);
5220
firstPageDate = cal.cfg.getProperty(cfgPageDate);
5221
Dom.addClass(cal.oDomContainer, firstClass);
5224
if (p==(pageCount-1)) {
5225
Dom.addClass(cal.oDomContainer, lastClass);
5231
this.pages[this.pages.length] = cal;
5236
* The default Config handler for the "pagedate" property
5237
* @method configPageDate
5238
* @param {String} type The CustomEvent type (usually the property name)
5239
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
5240
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
5242
configPageDate : function(type, args, obj) {
5246
var cfgPageDate = DEF_CFG.PAGEDATE.key;
5248
for (var p=0;p<this.pages.length;++p) {
5249
var cal = this.pages[p];
5251
firstPageDate = cal._parsePageDate(val);
5252
cal.cfg.setProperty(cfgPageDate, firstPageDate);
5254
var pageDate = new Date(firstPageDate);
5255
this._setMonthOnDate(pageDate, pageDate.getMonth() + p);
5256
cal.cfg.setProperty(cfgPageDate, pageDate);
5262
* The default Config handler for the CalendarGroup "selected" property
5263
* @method configSelected
5264
* @param {String} type The CustomEvent type (usually the property name)
5265
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
5266
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
5268
configSelected : function(type, args, obj) {
5269
var cfgSelected = DEF_CFG.SELECTED.key;
5270
this.delegateConfig(type, args, obj);
5271
var selected = (this.pages.length > 0) ? this.pages[0].cfg.getProperty(cfgSelected) : [];
5272
this.cfg.setProperty(cfgSelected, selected, true);
5277
* Delegates a configuration property to the CustomEvents associated with the CalendarGroup's children
5278
* @method delegateConfig
5279
* @param {String} type The CustomEvent type (usually the property name)
5280
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
5281
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
5283
delegateConfig : function(type, args, obj) {
5287
for (var p=0;p<this.pages.length;p++) {
5288
cal = this.pages[p];
5289
cal.cfg.setProperty(type, val);
5294
* Adds a function to all child Calendars within this CalendarGroup.
5295
* @method setChildFunction
5296
* @param {String} fnName The name of the function
5297
* @param {Function} fn The function to apply to each Calendar page object
5299
setChildFunction : function(fnName, fn) {
5300
var pageCount = this.cfg.getProperty(DEF_CFG.PAGES.key);
5302
for (var p=0;p<pageCount;++p) {
5303
this.pages[p][fnName] = fn;
5308
* Calls a function within all child Calendars within this CalendarGroup.
5309
* @method callChildFunction
5310
* @param {String} fnName The name of the function
5311
* @param {Array} args The arguments to pass to the function
5313
callChildFunction : function(fnName, args) {
5314
var pageCount = this.cfg.getProperty(DEF_CFG.PAGES.key);
5316
for (var p=0;p<pageCount;++p) {
5317
var page = this.pages[p];
5319
var fn = page[fnName];
5320
fn.call(page, args);
5326
* Constructs a child calendar. This method can be overridden if a subclassed version of the default
5327
* calendar is to be used.
5328
* @method constructChild
5329
* @param {String} id The id of the table element that will represent the calendar widget
5330
* @param {String} containerId The id of the container div element that will wrap the calendar table
5331
* @param {Object} config The configuration object containing the Calendar's arguments
5332
* @return {YAHOO.widget.Calendar} The YAHOO.widget.Calendar instance that is constructed
5334
constructChild : function(id,containerId,config) {
5335
var container = document.getElementById(containerId);
5337
container = document.createElement("div");
5338
container.id = containerId;
5339
this.oDomContainer.appendChild(container);
5341
return new Calendar(id,containerId,config);
5345
* Sets the calendar group's month explicitly. This month will be set into the first
5346
* page of the multi-page calendar, and all other months will be iterated appropriately.
5348
* @param {Number} month The numeric month, from 0 (January) to 11 (December)
5350
setMonth : function(month) {
5351
month = parseInt(month, 10);
5354
var cfgPageDate = DEF_CFG.PAGEDATE.key;
5356
for (var p=0; p<this.pages.length; ++p) {
5357
var cal = this.pages[p];
5358
var pageDate = cal.cfg.getProperty(cfgPageDate);
5360
currYear = pageDate.getFullYear();
5362
pageDate.setFullYear(currYear);
5364
this._setMonthOnDate(pageDate, month+p);
5365
cal.cfg.setProperty(cfgPageDate, pageDate);
5370
* Sets the calendar group's year explicitly. This year will be set into the first
5371
* page of the multi-page calendar, and all other months will be iterated appropriately.
5373
* @param {Number} year The numeric 4-digit year
5375
setYear : function(year) {
5377
var cfgPageDate = DEF_CFG.PAGEDATE.key;
5379
year = parseInt(year, 10);
5380
for (var p=0;p<this.pages.length;++p) {
5381
var cal = this.pages[p];
5382
var pageDate = cal.cfg.getProperty(cfgPageDate);
5384
if ((pageDate.getMonth()+1) == 1 && p>0) {
5392
* Calls the render function of all child calendars within the group.
5395
render : function() {
5396
this.renderHeader();
5397
for (var p=0;p<this.pages.length;++p) {
5398
var cal = this.pages[p];
5401
this.renderFooter();
5405
* Selects a date or a collection of dates on the current calendar. This method, by default,
5406
* does not call the render method explicitly. Once selection has completed, render must be
5407
* called for the changes to be reflected visually.
5409
* @param {String/Date/Date[]} date The date string of dates to select in the current calendar. Valid formats are
5410
* individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006).
5411
* Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005).
5412
* This method can also take a JavaScript Date object or an array of Date objects.
5413
* @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected.
5415
select : function(date) {
5416
for (var p=0;p<this.pages.length;++p) {
5417
var cal = this.pages[p];
5420
return this.getSelectedDates();
5424
* Selects dates in the CalendarGroup based on the cell index provided. This method is used to select cells without having to do a full render. The selected style is applied to the cells directly.
5425
* The value of the MULTI_SELECT Configuration attribute will determine the set of dates which get selected.
5427
* <li>If MULTI_SELECT is false, selectCell will select the cell at the specified index for only the last displayed Calendar page.</li>
5428
* <li>If MULTI_SELECT is true, selectCell will select the cell at the specified index, on each displayed Calendar page.</li>
5430
* @method selectCell
5431
* @param {Number} cellIndex The index of the cell to be selected.
5432
* @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected.
5434
selectCell : function(cellIndex) {
5435
for (var p=0;p<this.pages.length;++p) {
5436
var cal = this.pages[p];
5437
cal.selectCell(cellIndex);
5439
return this.getSelectedDates();
5443
* Deselects a date or a collection of dates on the current calendar. This method, by default,
5444
* does not call the render method explicitly. Once deselection has completed, render must be
5445
* called for the changes to be reflected visually.
5447
* @param {String/Date/Date[]} date The date string of dates to deselect in the current calendar. Valid formats are
5448
* individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006).
5449
* Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005).
5450
* This method can also take a JavaScript Date object or an array of Date objects.
5451
* @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected.
5453
deselect : function(date) {
5454
for (var p=0;p<this.pages.length;++p) {
5455
var cal = this.pages[p];
5458
return this.getSelectedDates();
5462
* Deselects all dates on the current calendar.
5463
* @method deselectAll
5464
* @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected.
5465
* Assuming that this function executes properly, the return value should be an empty array.
5466
* However, the empty array is returned for the sake of being able to check the selection status
5469
deselectAll : function() {
5470
for (var p=0;p<this.pages.length;++p) {
5471
var cal = this.pages[p];
5474
return this.getSelectedDates();
5478
* Deselects dates in the CalendarGroup based on the cell index provided. This method is used to select cells without having to do a full render. The selected style is applied to the cells directly.
5479
* deselectCell will deselect the cell at the specified index on each displayed Calendar page.
5481
* @method deselectCell
5482
* @param {Number} cellIndex The index of the cell to deselect.
5483
* @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected.
5485
deselectCell : function(cellIndex) {
5486
for (var p=0;p<this.pages.length;++p) {
5487
var cal = this.pages[p];
5488
cal.deselectCell(cellIndex);
5490
return this.getSelectedDates();
5494
* Resets the calendar widget to the originally selected month and year, and
5495
* sets the calendar to the initial selection(s).
5498
reset : function() {
5499
for (var p=0;p<this.pages.length;++p) {
5500
var cal = this.pages[p];
5506
* Clears the selected dates in the current calendar widget and sets the calendar
5507
* to the current month and year.
5510
clear : function() {
5511
for (var p=0;p<this.pages.length;++p) {
5512
var cal = this.pages[p];
5516
this.cfg.setProperty(DEF_CFG.SELECTED.key, []);
5517
this.cfg.setProperty(DEF_CFG.PAGEDATE.key, new Date(this.pages[0].today.getTime()));
5522
* Navigates to the next month page in the calendar widget.
5525
nextMonth : function() {
5526
for (var p=0;p<this.pages.length;++p) {
5527
var cal = this.pages[p];
5533
* Navigates to the previous month page in the calendar widget.
5534
* @method previousMonth
5536
previousMonth : function() {
5537
for (var p=this.pages.length-1;p>=0;--p) {
5538
var cal = this.pages[p];
5539
cal.previousMonth();
5544
* Navigates to the next year in the currently selected month in the calendar widget.
5547
nextYear : function() {
5548
for (var p=0;p<this.pages.length;++p) {
5549
var cal = this.pages[p];
5555
* Navigates to the previous year in the currently selected month in the calendar widget.
5556
* @method previousYear
5558
previousYear : function() {
5559
for (var p=0;p<this.pages.length;++p) {
5560
var cal = this.pages[p];
5566
* Gets the list of currently selected dates from the calendar.
5567
* @return An array of currently selected JavaScript Date objects.
5570
getSelectedDates : function() {
5571
var returnDates = [];
5572
var selected = this.cfg.getProperty(DEF_CFG.SELECTED.key);
5573
for (var d=0;d<selected.length;++d) {
5574
var dateArray = selected[d];
5576
var date = DateMath.getDate(dateArray[0],dateArray[1]-1,dateArray[2]);
5577
returnDates.push(date);
5580
returnDates.sort( function(a,b) { return a-b; } );
5585
* Adds a renderer to the render stack. The function reference passed to this method will be executed
5586
* when a date cell matches the conditions specified in the date string for this renderer.
5587
* @method addRenderer
5588
* @param {String} sDates A date string to associate with the specified renderer. Valid formats
5589
* include date (12/24/2005), month/day (12/24), and range (12/1/2004-1/1/2005)
5590
* @param {Function} fnRender The function executed to render cells that match the render rules for this renderer.
5592
addRenderer : function(sDates, fnRender) {
5593
for (var p=0;p<this.pages.length;++p) {
5594
var cal = this.pages[p];
5595
cal.addRenderer(sDates, fnRender);
5600
* Adds a month to the render stack. The function reference passed to this method will be executed
5601
* when a date cell matches the month passed to this method.
5602
* @method addMonthRenderer
5603
* @param {Number} month The month (1-12) to associate with this renderer
5604
* @param {Function} fnRender The function executed to render cells that match the render rules for this renderer.
5606
addMonthRenderer : function(month, fnRender) {
5607
for (var p=0;p<this.pages.length;++p) {
5608
var cal = this.pages[p];
5609
cal.addMonthRenderer(month, fnRender);
5614
* Adds a weekday to the render stack. The function reference passed to this method will be executed
5615
* when a date cell matches the weekday passed to this method.
5616
* @method addWeekdayRenderer
5617
* @param {Number} weekday The weekday (1-7) to associate with this renderer. 1=Sunday, 2=Monday etc.
5618
* @param {Function} fnRender The function executed to render cells that match the render rules for this renderer.
5620
addWeekdayRenderer : function(weekday, fnRender) {
5621
for (var p=0;p<this.pages.length;++p) {
5622
var cal = this.pages[p];
5623
cal.addWeekdayRenderer(weekday, fnRender);
5628
* Removes all custom renderers added to the CalendarGroup through the addRenderer, addMonthRenderer and
5629
* addWeekRenderer methods. CalendarGroup's render method needs to be called to after removing renderers
5630
* to see the changes applied.
5632
* @method removeRenderers
5634
removeRenderers : function() {
5635
this.callChildFunction("removeRenderers");
5639
* Renders the header for the CalendarGroup.
5640
* @method renderHeader
5642
renderHeader : function() {
5643
// EMPTY DEFAULT IMPL
5647
* Renders a footer for the 2-up calendar container. By default, this method is
5649
* @method renderFooter
5651
renderFooter : function() {
5652
// EMPTY DEFAULT IMPL
5656
* Adds the designated number of months to the current calendar month, and sets the current
5657
* calendar page date to the new month.
5659
* @param {Number} count The number of months to add to the current calendar
5661
addMonths : function(count) {
5662
this.callChildFunction("addMonths", count);
5666
* Subtracts the designated number of months from the current calendar month, and sets the current
5667
* calendar page date to the new month.
5668
* @method subtractMonths
5669
* @param {Number} count The number of months to subtract from the current calendar
5671
subtractMonths : function(count) {
5672
this.callChildFunction("subtractMonths", count);
5676
* Adds the designated number of years to the current calendar, and sets the current
5677
* calendar page date to the new month.
5679
* @param {Number} count The number of years to add to the current calendar
5681
addYears : function(count) {
5682
this.callChildFunction("addYears", count);
5686
* Subtcats the designated number of years from the current calendar, and sets the current
5687
* calendar page date to the new month.
5688
* @method subtractYears
5689
* @param {Number} count The number of years to subtract from the current calendar
5691
subtractYears : function(count) {
5692
this.callChildFunction("subtractYears", count);
5696
* Returns the Calendar page instance which has a pagedate (month/year) matching the given date.
5697
* Returns null if no match is found.
5699
* @method getCalendarPage
5700
* @param {Date} date The JavaScript Date object for which a Calendar page is to be found.
5701
* @return {Calendar} The Calendar page instance representing the month to which the date
5704
getCalendarPage : function(date) {
5707
var y = date.getFullYear(),
5708
m = date.getMonth();
5710
var pages = this.pages;
5711
for (var i = 0; i < pages.length; ++i) {
5712
var pageDate = pages[i].cfg.getProperty("pagedate");
5713
if (pageDate.getFullYear() === y && pageDate.getMonth() === m) {
5723
* Sets the month on a Date object, taking into account year rollover if the month is less than 0 or greater than 11.
5724
* The Date object passed in is modified. It should be cloned before passing it into this method if the original value needs to be maintained
5725
* @method _setMonthOnDate
5727
* @param {Date} date The Date object on which to set the month index
5728
* @param {Number} iMonth The month index to set
5730
_setMonthOnDate : function(date, iMonth) {
5731
// Bug in Safari 1.3, 2.0 (WebKit build < 420), Date.setMonth does not work consistently if iMonth is not 0-11
5732
if (YAHOO.env.ua.webkit && YAHOO.env.ua.webkit < 420 && (iMonth < 0 || iMonth > 11)) {
5733
var newDate = DateMath.add(date, DateMath.MONTH, iMonth-date.getMonth());
5734
date.setTime(newDate.getTime());
5736
date.setMonth(iMonth);
5741
* Fixes the width of the CalendarGroup container element, to account for miswrapped floats
5745
_fixWidth : function() {
5747
for (var p=0;p<this.pages.length;++p) {
5748
var cal = this.pages[p];
5749
w += cal.oDomContainer.offsetWidth;
5752
this.oDomContainer.style.width = w + "px";
5757
* Returns a string representation of the object.
5759
* @return {String} A string representation of the CalendarGroup object.
5761
toString : function() {
5762
return "CalendarGroup " + this.id;
5766
* Destroys the CalendarGroup instance. The method will remove references
5767
* to HTML elements, remove any event listeners added by the CalendarGroup.
5769
* It will also destroy the Config and CalendarNavigator instances created by the
5770
* CalendarGroup and the individual Calendar instances created for each page.
5774
destroy : function() {
5776
if (this.beforeDestroyEvent.fire()) {
5781
if (cal.navigator) {
5782
cal.navigator.destroy();
5789
// DOM event listeners
5790
Event.purgeElement(cal.oDomContainer, true);
5792
// Generated markup/DOM - Not removing the container DIV since we didn't create it.
5793
Dom.removeClass(cal.oDomContainer, CalendarGroup.CSS_CONTAINER);
5794
Dom.removeClass(cal.oDomContainer, CalendarGroup.CSS_MULTI_UP);
5796
for (var i = 0, l = cal.pages.length; i < l; i++) {
5797
cal.pages[i].destroy();
5798
cal.pages[i] = null;
5801
cal.oDomContainer.innerHTML = "";
5803
// JS-to-DOM references
5804
cal.oDomContainer = null;
5806
this.destroyEvent.fire();
5812
* CSS class representing the container for the calendar
5813
* @property YAHOO.widget.CalendarGroup.CSS_CONTAINER
5818
CalendarGroup.CSS_CONTAINER = "yui-calcontainer";
5821
* CSS class representing the container for the calendar
5822
* @property YAHOO.widget.CalendarGroup.CSS_MULTI_UP
5827
CalendarGroup.CSS_MULTI_UP = "multi";
5830
* CSS class representing the title for the 2-up calendar
5831
* @property YAHOO.widget.CalendarGroup.CSS_2UPTITLE
5836
CalendarGroup.CSS_2UPTITLE = "title";
5839
* CSS class representing the close icon for the 2-up calendar
5840
* @property YAHOO.widget.CalendarGroup.CSS_2UPCLOSE
5843
* @deprecated Along with Calendar.IMG_ROOT and NAV_ARROW_LEFT, NAV_ARROW_RIGHT configuration properties.
5844
* Calendar's <a href="YAHOO.widget.Calendar.html#Style.CSS_CLOSE">Style.CSS_CLOSE</a> property now represents the CSS class used to render the close icon
5847
CalendarGroup.CSS_2UPCLOSE = "close-icon";
5849
YAHOO.lang.augmentProto(CalendarGroup, Calendar, "buildDayLabel",
5851
"renderOutOfBoundsDate",
5854
"renderCellDefault",
5856
"renderCellStyleHighlight1",
5857
"renderCellStyleHighlight2",
5858
"renderCellStyleHighlight3",
5859
"renderCellStyleHighlight4",
5860
"renderCellStyleToday",
5861
"renderCellStyleSelected",
5862
"renderCellNotThisMonth",
5863
"renderBodyCellRestricted",
5871
"createCloseButton",
5873
"removeCloseButton",
5881
YAHOO.widget.CalGrp = CalendarGroup;
5882
YAHOO.widget.CalendarGroup = CalendarGroup;
5885
* @class YAHOO.widget.Calendar2up
5886
* @extends YAHOO.widget.CalendarGroup
5887
* @deprecated The old Calendar2up class is no longer necessary, since CalendarGroup renders in a 2up view by default.
5889
YAHOO.widget.Calendar2up = function(id, containerId, config) {
5890
this.init(id, containerId, config);
5893
YAHOO.extend(YAHOO.widget.Calendar2up, CalendarGroup);
5896
* @deprecated The old Calendar2up class is no longer necessary, since CalendarGroup renders in a 2up view by default.
5898
YAHOO.widget.Cal2up = YAHOO.widget.Calendar2up;
5903
* The CalendarNavigator is used along with a Calendar/CalendarGroup to
5904
* provide a Month/Year popup navigation control, allowing the user to navigate
5905
* to a specific month/year in the Calendar/CalendarGroup without having to
5906
* scroll through months sequentially
5908
* @namespace YAHOO.widget
5909
* @class CalendarNavigator
5911
* @param {Calendar|CalendarGroup} cal The instance of the Calendar or CalendarGroup to which this CalendarNavigator should be attached.
5913
YAHOO.widget.CalendarNavigator = function(cal) {
5918
// Setup static properties (inside anon fn, so that we can use shortcuts)
5919
var CN = YAHOO.widget.CalendarNavigator;
5922
* YAHOO.widget.CalendarNavigator.CLASSES contains constants
5923
* for the class values applied to the CalendarNaviatgator's
5925
* @property YAHOO.widget.CalendarNavigator.CLASSES
5931
* Class applied to the Calendar Navigator's bounding box
5932
* @property YAHOO.widget.CalendarNavigator.CLASSES.NAV
5938
* Class applied to the Calendar/CalendarGroup's bounding box to indicate
5939
* the Navigator is currently visible
5940
* @property YAHOO.widget.CalendarNavigator.CLASSES.NAV_VISIBLE
5944
NAV_VISIBLE: "yui-cal-nav-visible",
5946
* Class applied to the Navigator mask's bounding box
5947
* @property YAHOO.widget.CalendarNavigator.CLASSES.MASK
5951
MASK : "yui-cal-nav-mask",
5953
* Class applied to the year label/control bounding box
5954
* @property YAHOO.widget.CalendarNavigator.CLASSES.YEAR
5958
YEAR : "yui-cal-nav-y",
5960
* Class applied to the month label/control bounding box
5961
* @property YAHOO.widget.CalendarNavigator.CLASSES.MONTH
5965
MONTH : "yui-cal-nav-m",
5967
* Class applied to the submit/cancel button's bounding box
5968
* @property YAHOO.widget.CalendarNavigator.CLASSES.BUTTONS
5972
BUTTONS : "yui-cal-nav-b",
5974
* Class applied to buttons wrapping element
5975
* @property YAHOO.widget.CalendarNavigator.CLASSES.BUTTON
5979
BUTTON : "yui-cal-nav-btn",
5981
* Class applied to the validation error area's bounding box
5982
* @property YAHOO.widget.CalendarNavigator.CLASSES.ERROR
5986
ERROR : "yui-cal-nav-e",
5988
* Class applied to the year input control
5989
* @property YAHOO.widget.CalendarNavigator.CLASSES.YEAR_CTRL
5993
YEAR_CTRL : "yui-cal-nav-yc",
5995
* Class applied to the month input control
5996
* @property YAHOO.widget.CalendarNavigator.CLASSES.MONTH_CTRL
6000
MONTH_CTRL : "yui-cal-nav-mc",
6002
* Class applied to controls with invalid data (e.g. a year input field with invalid an year)
6003
* @property YAHOO.widget.CalendarNavigator.CLASSES.INVALID
6007
INVALID : "yui-invalid",
6009
* Class applied to default controls
6010
* @property YAHOO.widget.CalendarNavigator.CLASSES.DEFAULT
6014
DEFAULT : "yui-default"
6018
* Object literal containing the default configuration values for the CalendarNavigator
6019
* The configuration object is expected to follow the format below, with the properties being
6023
* <dd><em>Object</em> : An object with the properties shown below, defining the string labels to use in the Navigator's UI
6025
* <dt>month</dt><dd><em>String</em> : The string to use for the month label. Defaults to "Month".</dd>
6026
* <dt>year</dt><dd><em>String</em> : The string to use for the year label. Defaults to "Year".</dd>
6027
* <dt>submit</dt><dd><em>String</em> : The string to use for the submit button label. Defaults to "Okay".</dd>
6028
* <dt>cancel</dt><dd><em>String</em> : The string to use for the cancel button label. Defaults to "Cancel".</dd>
6029
* <dt>invalidYear</dt><dd><em>String</em> : The string to use for invalid year values. Defaults to "Year needs to be a number".</dd>
6032
* <dt>monthFormat</dt><dd><em>String</em> : The month format to use. Either YAHOO.widget.Calendar.LONG, or YAHOO.widget.Calendar.SHORT. Defaults to YAHOO.widget.Calendar.LONG</dd>
6033
* <dt>initialFocus</dt><dd><em>String</em> : Either "year" or "month" specifying which input control should get initial focus. Defaults to "year"</dd>
6035
* @property _DEFAULT_CFG
6046
invalidYear : "Year needs to be a number"
6048
monthFormat: YAHOO.widget.Calendar.LONG,
6049
initialFocus: "year"
6053
* The suffix added to the Calendar/CalendarGroup's ID, to generate
6054
* a unique ID for the Navigator and it's bounding box.
6055
* @property YAHOO.widget.CalendarNavigator.ID_SUFFIX
6060
CN.ID_SUFFIX = "_nav";
6062
* The suffix added to the Navigator's ID, to generate
6063
* a unique ID for the month control.
6064
* @property YAHOO.widget.CalendarNavigator.MONTH_SUFFIX
6069
CN.MONTH_SUFFIX = "_month";
6071
* The suffix added to the Navigator's ID, to generate
6072
* a unique ID for the year control.
6073
* @property YAHOO.widget.CalendarNavigator.YEAR_SUFFIX
6078
CN.YEAR_SUFFIX = "_year";
6080
* The suffix added to the Navigator's ID, to generate
6081
* a unique ID for the error bounding box.
6082
* @property YAHOO.widget.CalendarNavigator.ERROR_SUFFIX
6087
CN.ERROR_SUFFIX = "_error";
6089
* The suffix added to the Navigator's ID, to generate
6090
* a unique ID for the "Cancel" button.
6091
* @property YAHOO.widget.CalendarNavigator.CANCEL_SUFFIX
6096
CN.CANCEL_SUFFIX = "_cancel";
6098
* The suffix added to the Navigator's ID, to generate
6099
* a unique ID for the "Submit" button.
6100
* @property YAHOO.widget.CalendarNavigator.SUBMIT_SUFFIX
6105
CN.SUBMIT_SUFFIX = "_submit";
6108
* The number of digits to which the year input control is to be limited.
6109
* @property YAHOO.widget.CalendarNavigator.YR_MAX_DIGITS
6113
CN.YR_MAX_DIGITS = 4;
6116
* The amount by which to increment the current year value,
6117
* when the arrow up/down key is pressed on the year control
6118
* @property YAHOO.widget.CalendarNavigator.YR_MINOR_INC
6122
CN.YR_MINOR_INC = 1;
6125
* The amount by which to increment the current year value,
6126
* when the page up/down key is pressed on the year control
6127
* @property YAHOO.widget.CalendarNavigator.YR_MAJOR_INC
6131
CN.YR_MAJOR_INC = 10;
6134
* Artificial delay (in ms) between the time the Navigator is hidden
6135
* and the Calendar/CalendarGroup state is updated. Allows the user
6136
* the see the Calendar/CalendarGroup page changing. If set to 0
6137
* the Calendar/CalendarGroup page will be updated instantly
6138
* @property YAHOO.widget.CalendarNavigator.UPDATE_DELAY
6142
CN.UPDATE_DELAY = 50;
6145
* Regular expression used to validate the year input
6146
* @property YAHOO.widget.CalendarNavigator.YR_PATTERN
6150
CN.YR_PATTERN = /^\d+$/;
6152
* Regular expression used to trim strings
6153
* @property YAHOO.widget.CalendarNavigator.TRIM
6157
CN.TRIM = /^\s*(.*?)\s*$/;
6160
YAHOO.widget.CalendarNavigator.prototype = {
6163
* The unique ID for this CalendarNavigator instance
6170
* The Calendar/CalendarGroup instance to which the navigator belongs
6172
* @type {Calendar|CalendarGroup}
6177
* Reference to the HTMLElement used to render the navigator's bounding box
6184
* Reference to the HTMLElement used to render the navigator's mask
6191
* Reference to the HTMLElement used to input the year
6198
* Reference to the HTMLElement used to input the month
6205
* Reference to the HTMLElement used to display validation errors
6212
* Reference to the HTMLElement used to update the Calendar/Calendar group
6213
* with the month/year values
6214
* @property submitEl
6220
* Reference to the HTMLElement used to hide the navigator without updating the
6221
* Calendar/Calendar group
6222
* @property cancelEl
6228
* Reference to the first focusable control in the navigator (by default monthEl)
6229
* @property firstCtrl
6235
* Reference to the last focusable control in the navigator (by default cancelEl)
6236
* @property lastCtrl
6242
* The document containing the Calendar/Calendar group instance
6245
* @type HTMLDocument
6250
* Internal state property for the current year displayed in the navigator
6258
* Internal state property for the current month index displayed in the navigator
6266
* Private internal state property which indicates whether or not the
6267
* Navigator has been rendered.
6269
* @property __rendered
6275
* Init lifecycle method called as part of construction
6278
* @param {Calendar} cal The instance of the Calendar or CalendarGroup to which this CalendarNavigator should be attached
6280
init : function(cal) {
6281
var calBox = cal.oDomContainer;
6284
this.id = calBox.id + YAHOO.widget.CalendarNavigator.ID_SUFFIX;
6285
this._doc = calBox.ownerDocument;
6288
* Private flag, to identify IE Quirks
6290
* @property __isIEQuirks
6292
var ie = YAHOO.env.ua.ie;
6293
this.__isIEQuirks = (ie && ((ie <= 6) || (this._doc.compatMode == "BackCompat")));
6297
* Displays the navigator and mask, updating the input controls to reflect the
6298
* currently set month and year. The show method will invoke the render method
6299
* if the navigator has not been renderered already, allowing for lazy rendering
6302
* The show method will fire the Calendar/CalendarGroup's beforeShowNav and showNav events
6307
var CLASSES = YAHOO.widget.CalendarNavigator.CLASSES;
6309
if (this.cal.beforeShowNavEvent.fire()) {
6310
if (!this.__rendered) {
6315
this._updateMonthUI();
6316
this._updateYearUI();
6317
this._show(this.navEl, true);
6319
this.setInitialFocus();
6322
YAHOO.util.Dom.addClass(this.cal.oDomContainer, CLASSES.NAV_VISIBLE);
6323
this.cal.showNavEvent.fire();
6328
* Hides the navigator and mask
6330
* The show method will fire the Calendar/CalendarGroup's beforeHideNav event and hideNav events
6334
var CLASSES = YAHOO.widget.CalendarNavigator.CLASSES;
6336
if (this.cal.beforeHideNavEvent.fire()) {
6337
this._show(this.navEl, false);
6339
YAHOO.util.Dom.removeClass(this.cal.oDomContainer, CLASSES.NAV_VISIBLE);
6340
this.cal.hideNavEvent.fire();
6346
* Displays the navigator's mask element
6350
showMask : function() {
6351
this._show(this.maskEl, true);
6352
if (this.__isIEQuirks) {
6358
* Hides the navigator's mask element
6362
hideMask : function() {
6363
this._show(this.maskEl, false);
6367
* Returns the current month set on the navigator
6369
* Note: This may not be the month set in the UI, if
6370
* the UI contains an invalid value.
6373
* @return {Number} The Navigator's current month index
6375
getMonth: function() {
6380
* Returns the current year set on the navigator
6382
* Note: This may not be the year set in the UI, if
6383
* the UI contains an invalid value.
6386
* @return {Number} The Navigator's current year value
6388
getYear: function() {
6393
* Sets the current month on the Navigator, and updates the UI
6396
* @param {Number} nMonth The month index, from 0 (Jan) through 11 (Dec).
6398
setMonth : function(nMonth) {
6399
if (nMonth >= 0 && nMonth < 12) {
6400
this._month = nMonth;
6402
this._updateMonthUI();
6406
* Sets the current year on the Navigator, and updates the UI. If the
6407
* provided year is invalid, it will not be set.
6410
* @param {Number} nYear The full year value to set the Navigator to.
6412
setYear : function(nYear) {
6413
var yrPattern = YAHOO.widget.CalendarNavigator.YR_PATTERN;
6414
if (YAHOO.lang.isNumber(nYear) && yrPattern.test(nYear+"")) {
6417
this._updateYearUI();
6421
* Renders the HTML for the navigator, adding it to the
6422
* document and attaches event listeners if it has not
6423
* already been rendered.
6427
render: function() {
6428
this.cal.beforeRenderNavEvent.fire();
6429
if (!this.__rendered) {
6432
this.applyListeners();
6433
this.__rendered = true;
6435
this.cal.renderNavEvent.fire();
6439
* Creates the navigator's containing HTMLElement, it's contents, and appends
6440
* the containg element to the Calendar/CalendarGroup's container.
6444
createNav : function() {
6445
var NAV = YAHOO.widget.CalendarNavigator;
6446
var doc = this._doc;
6448
var d = doc.createElement("div");
6449
d.className = NAV.CLASSES.NAV;
6451
var htmlBuf = this.renderNavContents([]);
6453
d.innerHTML = htmlBuf.join('');
6454
this.cal.oDomContainer.appendChild(d);
6458
this.yearEl = doc.getElementById(this.id + NAV.YEAR_SUFFIX);
6459
this.monthEl = doc.getElementById(this.id + NAV.MONTH_SUFFIX);
6460
this.errorEl = doc.getElementById(this.id + NAV.ERROR_SUFFIX);
6461
this.submitEl = doc.getElementById(this.id + NAV.SUBMIT_SUFFIX);
6462
this.cancelEl = doc.getElementById(this.id + NAV.CANCEL_SUFFIX);
6464
if (YAHOO.env.ua.gecko && this.yearEl && this.yearEl.type == "text") {
6465
// Avoid XUL error on focus, select [ https://bugzilla.mozilla.org/show_bug.cgi?id=236791,
6466
// supposedly fixed in 1.8.1, but there are reports of it still being around for methods other than blur ]
6467
this.yearEl.setAttribute("autocomplete", "off");
6470
this._setFirstLastElements();
6474
* Creates the Mask HTMLElement and appends it to the Calendar/CalendarGroups
6477
* @method createMask
6479
createMask : function() {
6480
var C = YAHOO.widget.CalendarNavigator.CLASSES;
6482
var d = this._doc.createElement("div");
6483
d.className = C.MASK;
6485
this.cal.oDomContainer.appendChild(d);
6490
* Used to set the width/height of the mask in pixels to match the Calendar Container.
6491
* Currently only used for IE6 or IE in quirks mode. The other A-Grade browser are handled using CSS (width/height 100%).
6493
* The method is also registered as an HTMLElement resize listener on the Calendars container element.
6498
_syncMask : function() {
6499
var c = this.cal.oDomContainer;
6500
if (c && this.maskEl) {
6501
var r = YAHOO.util.Dom.getRegion(c);
6502
YAHOO.util.Dom.setStyle(this.maskEl, "width", r.right - r.left + "px");
6503
YAHOO.util.Dom.setStyle(this.maskEl, "height", r.bottom - r.top + "px");
6508
* Renders the contents of the navigator
6510
* @method renderNavContents
6512
* @param {Array} html The HTML buffer to append the HTML to.
6513
* @return {Array} A reference to the buffer passed in.
6515
renderNavContents : function(html) {
6516
var NAV = YAHOO.widget.CalendarNavigator,
6518
h = html; // just to use a shorter name
6520
h[h.length] = '<div class="' + C.MONTH + '">';
6521
this.renderMonth(h);
6522
h[h.length] = '</div>';
6523
h[h.length] = '<div class="' + C.YEAR + '">';
6525
h[h.length] = '</div>';
6526
h[h.length] = '<div class="' + C.BUTTONS + '">';
6527
this.renderButtons(h);
6528
h[h.length] = '</div>';
6529
h[h.length] = '<div class="' + C.ERROR + '" id="' + this.id + NAV.ERROR_SUFFIX + '"></div>';
6535
* Renders the month label and control for the navigator
6537
* @method renderNavContents
6538
* @param {Array} html The HTML buffer to append the HTML to.
6539
* @return {Array} A reference to the buffer passed in.
6541
renderMonth : function(html) {
6542
var NAV = YAHOO.widget.CalendarNavigator,
6545
var id = this.id + NAV.MONTH_SUFFIX,
6546
mf = this.__getCfg("monthFormat"),
6547
months = this.cal.cfg.getProperty((mf == YAHOO.widget.Calendar.SHORT) ? "MONTHS_SHORT" : "MONTHS_LONG"),
6550
if (months && months.length > 0) {
6551
h[h.length] = '<label for="' + id + '">';
6552
h[h.length] = this.__getCfg("month", true);
6553
h[h.length] = '</label>';
6554
h[h.length] = '<select name="' + id + '" id="' + id + '" class="' + C.MONTH_CTRL + '">';
6555
for (var i = 0; i < months.length; i++) {
6556
h[h.length] = '<option value="' + i + '">';
6557
h[h.length] = months[i];
6558
h[h.length] = '</option>';
6560
h[h.length] = '</select>';
6566
* Renders the year label and control for the navigator
6568
* @method renderYear
6569
* @param {Array} html The HTML buffer to append the HTML to.
6570
* @return {Array} A reference to the buffer passed in.
6572
renderYear : function(html) {
6573
var NAV = YAHOO.widget.CalendarNavigator,
6576
var id = this.id + NAV.YEAR_SUFFIX,
6577
size = NAV.YR_MAX_DIGITS,
6580
h[h.length] = '<label for="' + id + '">';
6581
h[h.length] = this.__getCfg("year", true);
6582
h[h.length] = '</label>';
6583
h[h.length] = '<input type="text" name="' + id + '" id="' + id + '" class="' + C.YEAR_CTRL + '" maxlength="' + size + '"/>';
6588
* Renders the submit/cancel buttons for the navigator
6590
* @method renderButton
6591
* @return {String} The HTML created for the Button UI
6593
renderButtons : function(html) {
6594
var C = YAHOO.widget.CalendarNavigator.CLASSES;
6597
h[h.length] = '<span class="' + C.BUTTON + ' ' + C.DEFAULT + '">';
6598
h[h.length] = '<button type="button" id="' + this.id + '_submit' + '">';
6599
h[h.length] = this.__getCfg("submit", true);
6600
h[h.length] = '</button>';
6601
h[h.length] = '</span>';
6602
h[h.length] = '<span class="' + C.BUTTON +'">';
6603
h[h.length] = '<button type="button" id="' + this.id + '_cancel' + '">';
6604
h[h.length] = this.__getCfg("cancel", true);
6605
h[h.length] = '</button>';
6606
h[h.length] = '</span>';
6612
* Attaches DOM event listeners to the rendered elements
6614
* The method will call applyKeyListeners, to setup keyboard specific
6617
* @method applyListeners
6619
applyListeners : function() {
6620
var E = YAHOO.util.Event;
6622
function yearUpdateHandler() {
6623
if (this.validate()) {
6624
this.setYear(this._getYearFromUI());
6628
function monthUpdateHandler() {
6629
this.setMonth(this._getMonthFromUI());
6632
E.on(this.submitEl, "click", this.submit, this, true);
6633
E.on(this.cancelEl, "click", this.cancel, this, true);
6634
E.on(this.yearEl, "blur", yearUpdateHandler, this, true);
6635
E.on(this.monthEl, "change", monthUpdateHandler, this, true);
6637
if (this.__isIEQuirks) {
6638
YAHOO.util.Event.on(this.cal.oDomContainer, "resize", this._syncMask, this, true);
6641
this.applyKeyListeners();
6645
* Removes/purges DOM event listeners from the rendered elements
6647
* @method purgeListeners
6649
purgeListeners : function() {
6650
var E = YAHOO.util.Event;
6651
E.removeListener(this.submitEl, "click", this.submit);
6652
E.removeListener(this.cancelEl, "click", this.cancel);
6653
E.removeListener(this.yearEl, "blur");
6654
E.removeListener(this.monthEl, "change");
6655
if (this.__isIEQuirks) {
6656
E.removeListener(this.cal.oDomContainer, "resize", this._syncMask);
6659
this.purgeKeyListeners();
6663
* Attaches DOM listeners for keyboard support.
6664
* Tab/Shift-Tab looping, Enter Key Submit on Year element,
6665
* Up/Down/PgUp/PgDown year increment on Year element
6667
* NOTE: MacOSX Safari 2.x doesn't let you tab to buttons and
6668
* MacOSX Gecko does not let you tab to buttons or select controls,
6669
* so for these browsers, Tab/Shift-Tab looping is limited to the
6670
* elements which can be reached using the tab key.
6672
* @method applyKeyListeners
6674
applyKeyListeners : function() {
6675
var E = YAHOO.util.Event,
6678
// IE/Safari 3.1 doesn't fire keypress for arrow/pg keys (non-char keys)
6679
var arrowEvt = (ua.ie || ua.webkit) ? "keydown" : "keypress";
6681
// - IE/Safari 3.1 doesn't fire keypress for non-char keys
6682
// - Opera doesn't allow us to cancel keydown or keypress for tab, but
6683
// changes focus successfully on keydown (keypress is too late to change focus - opera's already moved on).
6684
var tabEvt = (ua.ie || ua.opera || ua.webkit) ? "keydown" : "keypress";
6686
// Everyone likes keypress for Enter (char keys) - whoo hoo!
6687
E.on(this.yearEl, "keypress", this._handleEnterKey, this, true);
6689
E.on(this.yearEl, arrowEvt, this._handleDirectionKeys, this, true);
6690
E.on(this.lastCtrl, tabEvt, this._handleTabKey, this, true);
6691
E.on(this.firstCtrl, tabEvt, this._handleShiftTabKey, this, true);
6695
* Removes/purges DOM listeners for keyboard support
6697
* @method purgeKeyListeners
6699
purgeKeyListeners : function() {
6700
var E = YAHOO.util.Event,
6703
var arrowEvt = (ua.ie || ua.webkit) ? "keydown" : "keypress";
6704
var tabEvt = (ua.ie || ua.opera || ua.webkit) ? "keydown" : "keypress";
6706
E.removeListener(this.yearEl, "keypress", this._handleEnterKey);
6707
E.removeListener(this.yearEl, arrowEvt, this._handleDirectionKeys);
6708
E.removeListener(this.lastCtrl, tabEvt, this._handleTabKey);
6709
E.removeListener(this.firstCtrl, tabEvt, this._handleShiftTabKey);
6713
* Updates the Calendar/CalendarGroup's pagedate with the currently set month and year if valid.
6715
* If the currently set month/year is invalid, a validation error will be displayed and the
6716
* Calendar/CalendarGroup's pagedate will not be updated.
6720
submit : function() {
6721
if (this.validate()) {
6724
this.setMonth(this._getMonthFromUI());
6725
this.setYear(this._getYearFromUI());
6729
// Artificial delay, just to help the user see something changed
6730
var delay = YAHOO.widget.CalendarNavigator.UPDATE_DELAY;
6733
window.setTimeout(function(){ nav._update(cal); }, delay);
6741
* Updates the Calendar rendered state, based on the state of the CalendarNavigator
6743
* @param cal The Calendar instance to update
6746
_update : function(cal) {
6747
cal.setYear(this.getYear());
6748
cal.setMonth(this.getMonth());
6753
* Hides the navigator and mask, without updating the Calendar/CalendarGroup's state
6757
cancel : function() {
6762
* Validates the current state of the UI controls
6765
* @return {Boolean} true, if the current UI state contains valid values, false if not
6767
validate : function() {
6768
if (this._getYearFromUI() !== null) {
6772
this.setYearError();
6773
this.setError(this.__getCfg("invalidYear", true));
6779
* Displays an error message in the Navigator's error panel
6781
* @param {String} msg The error message to display
6783
setError : function(msg) {
6785
this.errorEl.innerHTML = msg;
6786
this._show(this.errorEl, true);
6791
* Clears the navigator's error message and hides the error panel
6792
* @method clearError
6794
clearError : function() {
6796
this.errorEl.innerHTML = "";
6797
this._show(this.errorEl, false);
6802
* Displays the validation error UI for the year control
6803
* @method setYearError
6805
setYearError : function() {
6806
YAHOO.util.Dom.addClass(this.yearEl, YAHOO.widget.CalendarNavigator.CLASSES.INVALID);
6810
* Removes the validation error UI for the year control
6811
* @method clearYearError
6813
clearYearError : function() {
6814
YAHOO.util.Dom.removeClass(this.yearEl, YAHOO.widget.CalendarNavigator.CLASSES.INVALID);
6818
* Clears all validation and error messages in the UI
6819
* @method clearErrors
6821
clearErrors : function() {
6823
this.clearYearError();
6827
* Sets the initial focus, based on the configured value
6828
* @method setInitialFocus
6830
setInitialFocus : function() {
6831
var el = this.submitEl,
6832
f = this.__getCfg("initialFocus");
6834
if (f && f.toLowerCase) {
6835
f = f.toLowerCase();
6839
this.yearEl.select();
6843
} else if (f == "month") {
6848
if (el && YAHOO.lang.isFunction(el.focus)) {
6851
} catch (focusErr) {
6852
// TODO: Fall back if focus fails?
6858
* Removes all renderered HTML elements for the Navigator from
6859
* the DOM, purges event listeners and clears (nulls) any property
6860
* references to HTML references
6863
erase : function() {
6864
if (this.__rendered) {
6865
this.purgeListeners();
6867
// Clear out innerHTML references
6869
this.monthEl = null;
6870
this.errorEl = null;
6871
this.submitEl = null;
6872
this.cancelEl = null;
6873
this.firstCtrl = null;
6874
this.lastCtrl = null;
6876
this.navEl.innerHTML = "";
6879
var p = this.navEl.parentNode;
6881
p.removeChild(this.navEl);
6885
var pm = this.maskEl.parentNode;
6887
pm.removeChild(this.maskEl);
6890
this.__rendered = false;
6895
* Destroys the Navigator object and any HTML references
6898
destroy : function() {
6906
* Protected implementation to handle how UI elements are
6912
_show : function(el, bShow) {
6914
YAHOO.util.Dom.setStyle(el, "display", (bShow) ? "block" : "none");
6919
* Returns the month value (index), from the month UI element
6921
* @method _getMonthFromUI
6922
* @return {Number} The month index, or 0 if a UI element for the month
6925
_getMonthFromUI : function() {
6927
return this.monthEl.selectedIndex;
6929
return 0; // Default to Jan
6934
* Returns the year value, from the Navitator's year UI element
6936
* @method _getYearFromUI
6937
* @return {Number} The year value set in the UI, if valid. null is returned if
6938
* the UI does not contain a valid year value.
6940
_getYearFromUI : function() {
6941
var NAV = YAHOO.widget.CalendarNavigator;
6945
var value = this.yearEl.value;
6946
value = value.replace(NAV.TRIM, "$1");
6948
if (NAV.YR_PATTERN.test(value)) {
6949
yr = parseInt(value, 10);
6956
* Updates the Navigator's year UI, based on the year value set on the Navigator object
6958
* @method _updateYearUI
6960
_updateYearUI : function() {
6961
if (this.yearEl && this._year !== null) {
6962
this.yearEl.value = this._year;
6967
* Updates the Navigator's month UI, based on the month value set on the Navigator object
6969
* @method _updateMonthUI
6971
_updateMonthUI : function() {
6973
this.monthEl.selectedIndex = this._month;
6978
* Sets up references to the first and last focusable element in the Navigator's UI
6979
* in terms of tab order (Naviagator's firstEl and lastEl properties). The references
6980
* are used to control modality by looping around from the first to the last control
6981
* and visa versa for tab/shift-tab navigation.
6983
* See <a href="#applyKeyListeners">applyKeyListeners</a>
6986
* @method _setFirstLastElements
6988
_setFirstLastElements : function() {
6989
this.firstCtrl = this.monthEl;
6990
this.lastCtrl = this.cancelEl;
6992
// Special handling for MacOSX.
6993
// - Safari 2.x can't focus on buttons
6994
// - Gecko can't focus on select boxes or buttons
6996
if (YAHOO.env.ua.webkit && YAHOO.env.ua.webkit < 420){
6997
this.firstCtrl = this.monthEl;
6998
this.lastCtrl = this.yearEl;
7000
if (YAHOO.env.ua.gecko) {
7001
this.firstCtrl = this.yearEl;
7002
this.lastCtrl = this.yearEl;
7008
* Default Keyboard event handler to capture Enter
7009
* on the Navigator's year control (yearEl)
7011
* @method _handleEnterKey
7013
* @param {Event} e The DOM event being handled
7015
_handleEnterKey : function(e) {
7016
var KEYS = YAHOO.util.KeyListener.KEY;
7018
if (YAHOO.util.Event.getCharCode(e) == KEYS.ENTER) {
7019
YAHOO.util.Event.preventDefault(e);
7025
* Default Keyboard event handler to capture up/down/pgup/pgdown
7026
* on the Navigator's year control (yearEl).
7028
* @method _handleDirectionKeys
7030
* @param {Event} e The DOM event being handled
7032
_handleDirectionKeys : function(e) {
7033
var E = YAHOO.util.Event,
7034
KEYS = YAHOO.util.KeyListener.KEY,
7035
NAV = YAHOO.widget.CalendarNavigator;
7037
var value = (this.yearEl.value) ? parseInt(this.yearEl.value, 10) : null;
7038
if (isFinite(value)) {
7040
switch(E.getCharCode(e)) {
7042
this.yearEl.value = value + NAV.YR_MINOR_INC;
7046
this.yearEl.value = Math.max(value - NAV.YR_MINOR_INC, 0);
7050
this.yearEl.value = value + NAV.YR_MAJOR_INC;
7053
case KEYS.PAGE_DOWN:
7054
this.yearEl.value = Math.max(value - NAV.YR_MAJOR_INC, 0);
7061
E.preventDefault(e);
7063
this.yearEl.select();
7072
* Default Keyboard event handler to capture Tab
7073
* on the last control (lastCtrl) in the Navigator.
7075
* @method _handleTabKey
7077
* @param {Event} e The DOM event being handled
7079
_handleTabKey : function(e) {
7080
var E = YAHOO.util.Event,
7081
KEYS = YAHOO.util.KeyListener.KEY;
7083
if (E.getCharCode(e) == KEYS.TAB && !e.shiftKey) {
7085
E.preventDefault(e);
7086
this.firstCtrl.focus();
7088
// Ignore - mainly for focus edge cases
7094
* Default Keyboard event handler to capture Shift-Tab
7095
* on the first control (firstCtrl) in the Navigator.
7097
* @method _handleShiftTabKey
7099
* @param {Event} e The DOM event being handled
7101
_handleShiftTabKey : function(e) {
7102
var E = YAHOO.util.Event,
7103
KEYS = YAHOO.util.KeyListener.KEY;
7105
if (e.shiftKey && E.getCharCode(e) == KEYS.TAB) {
7107
E.preventDefault(e);
7108
this.lastCtrl.focus();
7110
// Ignore - mainly for focus edge cases
7116
* Retrieve Navigator configuration values from
7117
* the parent Calendar/CalendarGroup's config value.
7119
* If it has not been set in the user provided configuration, the method will
7120
* return the default value of the configuration property, as set in _DEFAULT_CFG
7124
* @param {String} Case sensitive property name.
7125
* @param {Boolean} true, if the property is a string property, false if not.
7126
* @return The value of the configuration property
7128
__getCfg : function(prop, bIsStr) {
7129
var DEF_CFG = YAHOO.widget.CalendarNavigator._DEFAULT_CFG;
7130
var cfg = this.cal.cfg.getProperty("navigator");
7133
return (cfg !== true && cfg.strings && cfg.strings[prop]) ? cfg.strings[prop] : DEF_CFG.strings[prop];
7135
return (cfg !== true && cfg[prop]) ? cfg[prop] : DEF_CFG[prop];
7140
* Private flag, to identify MacOS
7144
__isMac : (navigator.userAgent.toLowerCase().indexOf("macintosh") != -1)
7148
YAHOO.register("calendar", YAHOO.widget.Calendar, {version: "2.7.0", build: "1799"});