Mercurial > kallithea
annotate rhodecode/public/js/yui/calendar/calendar-debug.js @ 1073:289ff43cc190 beta
update YUI dev libs to latest version
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Sun, 20 Feb 2011 20:58:07 +0100 |
parents | 1e757ac98988 |
children |
rev | line source |
---|---|
0 | 1 /* |
1073
289ff43cc190
update YUI dev libs to latest version
Marcin Kuzminski <marcin@python-works.com>
parents:
547
diff
changeset
|
2 Copyright (c) 2010, Yahoo! Inc. All rights reserved. |
0 | 3 Code licensed under the BSD License: |
1073
289ff43cc190
update YUI dev libs to latest version
Marcin Kuzminski <marcin@python-works.com>
parents:
547
diff
changeset
|
4 http://developer.yahoo.com/yui/license.html |
289ff43cc190
update YUI dev libs to latest version
Marcin Kuzminski <marcin@python-works.com>
parents:
547
diff
changeset
|
5 version: 2.8.2r1 |
0 | 6 */ |
7 (function () { | |
8 | |
9 /** | |
10 * Config is a utility used within an Object to allow the implementer to | |
11 * maintain a list of local configuration properties and listen for changes | |
12 * to those properties dynamically using CustomEvent. The initial values are | |
13 * also maintained so that the configuration can be reset at any given point | |
14 * to its initial state. | |
15 * @namespace YAHOO.util | |
16 * @class Config | |
17 * @constructor | |
18 * @param {Object} owner The owner Object to which this Config Object belongs | |
19 */ | |
20 YAHOO.util.Config = function (owner) { | |
21 | |
22 if (owner) { | |
23 this.init(owner); | |
24 } | |
25 | |
26 if (!owner) { YAHOO.log("No owner specified for Config object", "error", "Config"); } | |
27 | |
28 }; | |
29 | |
30 | |
31 var Lang = YAHOO.lang, | |
32 CustomEvent = YAHOO.util.CustomEvent, | |
33 Config = YAHOO.util.Config; | |
34 | |
35 | |
36 /** | |
37 * Constant representing the CustomEvent type for the config changed event. | |
38 * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT | |
39 * @private | |
40 * @static | |
41 * @final | |
42 */ | |
43 Config.CONFIG_CHANGED_EVENT = "configChanged"; | |
44 | |
45 /** | |
46 * Constant representing the boolean type string | |
47 * @property YAHOO.util.Config.BOOLEAN_TYPE | |
48 * @private | |
49 * @static | |
50 * @final | |
51 */ | |
52 Config.BOOLEAN_TYPE = "boolean"; | |
53 | |
54 Config.prototype = { | |
55 | |
56 /** | |
57 * Object reference to the owner of this Config Object | |
58 * @property owner | |
59 * @type Object | |
60 */ | |
61 owner: null, | |
62 | |
63 /** | |
64 * Boolean flag that specifies whether a queue is currently | |
65 * being executed | |
66 * @property queueInProgress | |
67 * @type Boolean | |
68 */ | |
69 queueInProgress: false, | |
70 | |
71 /** | |
72 * Maintains the local collection of configuration property objects and | |
73 * their specified values | |
74 * @property config | |
75 * @private | |
76 * @type Object | |
77 */ | |
78 config: null, | |
79 | |
80 /** | |
81 * Maintains the local collection of configuration property objects as | |
82 * they were initially applied. | |
83 * This object is used when resetting a property. | |
84 * @property initialConfig | |
85 * @private | |
86 * @type Object | |
87 */ | |
88 initialConfig: null, | |
89 | |
90 /** | |
91 * Maintains the local, normalized CustomEvent queue | |
92 * @property eventQueue | |
93 * @private | |
94 * @type Object | |
95 */ | |
96 eventQueue: null, | |
97 | |
98 /** | |
99 * Custom Event, notifying subscribers when Config properties are set | |
100 * (setProperty is called without the silent flag | |
101 * @event configChangedEvent | |
102 */ | |
103 configChangedEvent: null, | |
104 | |
105 /** | |
106 * Initializes the configuration Object and all of its local members. | |
107 * @method init | |
108 * @param {Object} owner The owner Object to which this Config | |
109 * Object belongs | |
110 */ | |
111 init: function (owner) { | |
112 | |
113 this.owner = owner; | |
114 | |
115 this.configChangedEvent = | |
116 this.createEvent(Config.CONFIG_CHANGED_EVENT); | |
117 | |
118 this.configChangedEvent.signature = CustomEvent.LIST; | |
119 this.queueInProgress = false; | |
120 this.config = {}; | |
121 this.initialConfig = {}; | |
122 this.eventQueue = []; | |
123 | |
124 }, | |
125 | |
126 /** | |
127 * Validates that the value passed in is a Boolean. | |
128 * @method checkBoolean | |
129 * @param {Object} val The value to validate | |
130 * @return {Boolean} true, if the value is valid | |
131 */ | |
132 checkBoolean: function (val) { | |
133 return (typeof val == Config.BOOLEAN_TYPE); | |
134 }, | |
135 | |
136 /** | |
137 * Validates that the value passed in is a number. | |
138 * @method checkNumber | |
139 * @param {Object} val The value to validate | |
140 * @return {Boolean} true, if the value is valid | |
141 */ | |
142 checkNumber: function (val) { | |
143 return (!isNaN(val)); | |
144 }, | |
145 | |
146 /** | |
147 * Fires a configuration property event using the specified value. | |
148 * @method fireEvent | |
149 * @private | |
150 * @param {String} key The configuration property's name | |
151 * @param {value} Object The value of the correct type for the property | |
152 */ | |
153 fireEvent: function ( key, value ) { | |
154 YAHOO.log("Firing Config event: " + key + "=" + value, "info", "Config"); | |
155 var property = this.config[key]; | |
156 | |
157 if (property && property.event) { | |
158 property.event.fire(value); | |
159 } | |
160 }, | |
161 | |
162 /** | |
163 * Adds a property to the Config Object's private config hash. | |
164 * @method addProperty | |
165 * @param {String} key The configuration property's name | |
166 * @param {Object} propertyObject The Object containing all of this | |
167 * property's arguments | |
168 */ | |
169 addProperty: function ( key, propertyObject ) { | |
170 key = key.toLowerCase(); | |
171 YAHOO.log("Added property: " + key, "info", "Config"); | |
172 | |
173 this.config[key] = propertyObject; | |
174 | |
175 propertyObject.event = this.createEvent(key, { scope: this.owner }); | |
176 propertyObject.event.signature = CustomEvent.LIST; | |
177 | |
178 | |
179 propertyObject.key = key; | |
180 | |
181 if (propertyObject.handler) { | |
182 propertyObject.event.subscribe(propertyObject.handler, | |
183 this.owner); | |
184 } | |
185 | |
186 this.setProperty(key, propertyObject.value, true); | |
187 | |
188 if (! propertyObject.suppressEvent) { | |
189 this.queueProperty(key, propertyObject.value); | |
190 } | |
191 | |
192 }, | |
193 | |
194 /** | |
195 * Returns a key-value configuration map of the values currently set in | |
196 * the Config Object. | |
197 * @method getConfig | |
198 * @return {Object} The current config, represented in a key-value map | |
199 */ | |
200 getConfig: function () { | |
201 | |
202 var cfg = {}, | |
203 currCfg = this.config, | |
204 prop, | |
205 property; | |
206 | |
207 for (prop in currCfg) { | |
208 if (Lang.hasOwnProperty(currCfg, prop)) { | |
209 property = currCfg[prop]; | |
210 if (property && property.event) { | |
211 cfg[prop] = property.value; | |
212 } | |
213 } | |
214 } | |
215 | |
216 return cfg; | |
217 }, | |
218 | |
219 /** | |
220 * Returns the value of specified property. | |
221 * @method getProperty | |
222 * @param {String} key The name of the property | |
223 * @return {Object} The value of the specified property | |
224 */ | |
225 getProperty: function (key) { | |
226 var property = this.config[key.toLowerCase()]; | |
227 if (property && property.event) { | |
228 return property.value; | |
229 } else { | |
230 return undefined; | |
231 } | |
232 }, | |
233 | |
234 /** | |
235 * Resets the specified property's value to its initial value. | |
236 * @method resetProperty | |
237 * @param {String} key The name of the property | |
238 * @return {Boolean} True is the property was reset, false if not | |
239 */ | |
240 resetProperty: function (key) { | |
241 | |
242 key = key.toLowerCase(); | |
243 | |
244 var property = this.config[key]; | |
245 | |
246 if (property && property.event) { | |
247 | |
248 if (this.initialConfig[key] && | |
249 !Lang.isUndefined(this.initialConfig[key])) { | |
250 | |
251 this.setProperty(key, this.initialConfig[key]); | |
252 | |
253 return true; | |
254 | |
255 } | |
256 | |
257 } else { | |
258 | |
259 return false; | |
260 } | |
261 | |
262 }, | |
263 | |
264 /** | |
265 * Sets the value of a property. If the silent property is passed as | |
266 * true, the property's event will not be fired. | |
267 * @method setProperty | |
268 * @param {String} key The name of the property | |
269 * @param {String} value The value to set the property to | |
270 * @param {Boolean} silent Whether the value should be set silently, | |
271 * without firing the property event. | |
272 * @return {Boolean} True, if the set was successful, false if it failed. | |
273 */ | |
274 setProperty: function (key, value, silent) { | |
275 | |
276 var property; | |
277 | |
278 key = key.toLowerCase(); | |
279 YAHOO.log("setProperty: " + key + "=" + value, "info", "Config"); | |
280 | |
281 if (this.queueInProgress && ! silent) { | |
282 // Currently running through a queue... | |
283 this.queueProperty(key,value); | |
284 return true; | |
285 | |
286 } else { | |
287 property = this.config[key]; | |
288 if (property && property.event) { | |
289 if (property.validator && !property.validator(value)) { | |
290 return false; | |
291 } else { | |
292 property.value = value; | |
293 if (! silent) { | |
294 this.fireEvent(key, value); | |
295 this.configChangedEvent.fire([key, value]); | |
296 } | |
297 return true; | |
298 } | |
299 } else { | |
300 return false; | |
301 } | |
302 } | |
303 }, | |
304 | |
305 /** | |
306 * Sets the value of a property and queues its event to execute. If the | |
307 * event is already scheduled to execute, it is | |
308 * moved from its current position to the end of the queue. | |
309 * @method queueProperty | |
310 * @param {String} key The name of the property | |
311 * @param {String} value The value to set the property to | |
312 * @return {Boolean} true, if the set was successful, false if | |
313 * it failed. | |
314 */ | |
315 queueProperty: function (key, value) { | |
316 | |
317 key = key.toLowerCase(); | |
318 YAHOO.log("queueProperty: " + key + "=" + value, "info", "Config"); | |
319 | |
320 var property = this.config[key], | |
321 foundDuplicate = false, | |
322 iLen, | |
323 queueItem, | |
324 queueItemKey, | |
325 queueItemValue, | |
326 sLen, | |
327 supercedesCheck, | |
328 qLen, | |
329 queueItemCheck, | |
330 queueItemCheckKey, | |
331 queueItemCheckValue, | |
332 i, | |
333 s, | |
334 q; | |
335 | |
336 if (property && property.event) { | |
337 | |
338 if (!Lang.isUndefined(value) && property.validator && | |
339 !property.validator(value)) { // validator | |
340 return false; | |
341 } else { | |
342 | |
343 if (!Lang.isUndefined(value)) { | |
344 property.value = value; | |
345 } else { | |
346 value = property.value; | |
347 } | |
348 | |
349 foundDuplicate = false; | |
350 iLen = this.eventQueue.length; | |
351 | |
352 for (i = 0; i < iLen; i++) { | |
353 queueItem = this.eventQueue[i]; | |
354 | |
355 if (queueItem) { | |
356 queueItemKey = queueItem[0]; | |
357 queueItemValue = queueItem[1]; | |
358 | |
359 if (queueItemKey == key) { | |
360 | |
361 /* | |
362 found a dupe... push to end of queue, null | |
363 current item, and break | |
364 */ | |
365 | |
366 this.eventQueue[i] = null; | |
367 | |
368 this.eventQueue.push( | |
369 [key, (!Lang.isUndefined(value) ? | |
370 value : queueItemValue)]); | |
371 | |
372 foundDuplicate = true; | |
373 break; | |
374 } | |
375 } | |
376 } | |
377 | |
378 // this is a refire, or a new property in the queue | |
379 | |
380 if (! foundDuplicate && !Lang.isUndefined(value)) { | |
381 this.eventQueue.push([key, value]); | |
382 } | |
383 } | |
384 | |
385 if (property.supercedes) { | |
386 | |
387 sLen = property.supercedes.length; | |
388 | |
389 for (s = 0; s < sLen; s++) { | |
390 | |
391 supercedesCheck = property.supercedes[s]; | |
392 qLen = this.eventQueue.length; | |
393 | |
394 for (q = 0; q < qLen; q++) { | |
395 queueItemCheck = this.eventQueue[q]; | |
396 | |
397 if (queueItemCheck) { | |
398 queueItemCheckKey = queueItemCheck[0]; | |
399 queueItemCheckValue = queueItemCheck[1]; | |
400 | |
401 if (queueItemCheckKey == | |
402 supercedesCheck.toLowerCase() ) { | |
403 | |
404 this.eventQueue.push([queueItemCheckKey, | |
405 queueItemCheckValue]); | |
406 | |
407 this.eventQueue[q] = null; | |
408 break; | |
409 | |
410 } | |
411 } | |
412 } | |
413 } | |
414 } | |
415 | |
416 YAHOO.log("Config event queue: " + this.outputEventQueue(), "info", "Config"); | |
417 | |
418 return true; | |
419 } else { | |
420 return false; | |
421 } | |
422 }, | |
423 | |
424 /** | |
425 * Fires the event for a property using the property's current value. | |
426 * @method refireEvent | |
427 * @param {String} key The name of the property | |
428 */ | |
429 refireEvent: function (key) { | |
430 | |
431 key = key.toLowerCase(); | |
432 | |
433 var property = this.config[key]; | |
434 | |
435 if (property && property.event && | |
436 | |
437 !Lang.isUndefined(property.value)) { | |
438 | |
439 if (this.queueInProgress) { | |
440 | |
441 this.queueProperty(key); | |
442 | |
443 } else { | |
444 | |
445 this.fireEvent(key, property.value); | |
446 | |
447 } | |
448 | |
449 } | |
450 }, | |
451 | |
452 /** | |
453 * Applies a key-value Object literal to the configuration, replacing | |
454 * any existing values, and queueing the property events. | |
455 * Although the values will be set, fireQueue() must be called for their | |
456 * associated events to execute. | |
457 * @method applyConfig | |
458 * @param {Object} userConfig The configuration Object literal | |
459 * @param {Boolean} init When set to true, the initialConfig will | |
460 * be set to the userConfig passed in, so that calling a reset will | |
461 * reset the properties to the passed values. | |
462 */ | |
463 applyConfig: function (userConfig, init) { | |
464 | |
465 var sKey, | |
466 oConfig; | |
467 | |
468 if (init) { | |
469 oConfig = {}; | |
470 for (sKey in userConfig) { | |
471 if (Lang.hasOwnProperty(userConfig, sKey)) { | |
472 oConfig[sKey.toLowerCase()] = userConfig[sKey]; | |
473 } | |
474 } | |
475 this.initialConfig = oConfig; | |
476 } | |
477 | |
478 for (sKey in userConfig) { | |
479 if (Lang.hasOwnProperty(userConfig, sKey)) { | |
480 this.queueProperty(sKey, userConfig[sKey]); | |
481 } | |
482 } | |
483 }, | |
484 | |
485 /** | |
486 * Refires the events for all configuration properties using their | |
487 * current values. | |
488 * @method refresh | |
489 */ | |
490 refresh: function () { | |
491 | |
492 var prop; | |
493 | |
494 for (prop in this.config) { | |
495 if (Lang.hasOwnProperty(this.config, prop)) { | |
496 this.refireEvent(prop); | |
497 } | |
498 } | |
499 }, | |
500 | |
501 /** | |
502 * Fires the normalized list of queued property change events | |
503 * @method fireQueue | |
504 */ | |
505 fireQueue: function () { | |
506 | |
507 var i, | |
508 queueItem, | |
509 key, | |
510 value, | |
511 property; | |
512 | |
513 this.queueInProgress = true; | |
514 for (i = 0;i < this.eventQueue.length; i++) { | |
515 queueItem = this.eventQueue[i]; | |
516 if (queueItem) { | |
517 | |
518 key = queueItem[0]; | |
519 value = queueItem[1]; | |
520 property = this.config[key]; | |
521 | |
522 property.value = value; | |
523 | |
524 // Clear out queue entry, to avoid it being | |
525 // re-added to the queue by any queueProperty/supercedes | |
526 // calls which are invoked during fireEvent | |
527 this.eventQueue[i] = null; | |
528 | |
529 this.fireEvent(key,value); | |
530 } | |
531 } | |
532 | |
533 this.queueInProgress = false; | |
534 this.eventQueue = []; | |
535 }, | |
536 | |
537 /** | |
538 * Subscribes an external handler to the change event for any | |
539 * given property. | |
540 * @method subscribeToConfigEvent | |
541 * @param {String} key The property name | |
542 * @param {Function} handler The handler function to use subscribe to | |
543 * the property's event | |
544 * @param {Object} obj The Object to use for scoping the event handler | |
545 * (see CustomEvent documentation) | |
546 * @param {Boolean} overrideContext Optional. If true, will override | |
547 * "this" within the handler to map to the scope Object passed into the | |
548 * method. | |
549 * @return {Boolean} True, if the subscription was successful, | |
550 * otherwise false. | |
551 */ | |
552 subscribeToConfigEvent: function (key, handler, obj, overrideContext) { | |
553 | |
554 var property = this.config[key.toLowerCase()]; | |
555 | |
556 if (property && property.event) { | |
557 if (!Config.alreadySubscribed(property.event, handler, obj)) { | |
558 property.event.subscribe(handler, obj, overrideContext); | |
559 } | |
560 return true; | |
561 } else { | |
562 return false; | |
563 } | |
564 | |
565 }, | |
566 | |
567 /** | |
568 * Unsubscribes an external handler from the change event for any | |
569 * given property. | |
570 * @method unsubscribeFromConfigEvent | |
571 * @param {String} key The property name | |
572 * @param {Function} handler The handler function to use subscribe to | |
573 * the property's event | |
574 * @param {Object} obj The Object to use for scoping the event | |
575 * handler (see CustomEvent documentation) | |
576 * @return {Boolean} True, if the unsubscription was successful, | |
577 * otherwise false. | |
578 */ | |
579 unsubscribeFromConfigEvent: function (key, handler, obj) { | |
580 var property = this.config[key.toLowerCase()]; | |
581 if (property && property.event) { | |
582 return property.event.unsubscribe(handler, obj); | |
583 } else { | |
584 return false; | |
585 } | |
586 }, | |
587 | |
588 /** | |
589 * Returns a string representation of the Config object | |
590 * @method toString | |
591 * @return {String} The Config object in string format. | |
592 */ | |
593 toString: function () { | |
594 var output = "Config"; | |
595 if (this.owner) { | |
596 output += " [" + this.owner.toString() + "]"; | |
597 } | |
598 return output; | |
599 }, | |
600 | |
601 /** | |
602 * Returns a string representation of the Config object's current | |
603 * CustomEvent queue | |
604 * @method outputEventQueue | |
605 * @return {String} The string list of CustomEvents currently queued | |
606 * for execution | |
607 */ | |
608 outputEventQueue: function () { | |
609 | |
610 var output = "", | |
611 queueItem, | |
612 q, | |
613 nQueue = this.eventQueue.length; | |
614 | |
615 for (q = 0; q < nQueue; q++) { | |
616 queueItem = this.eventQueue[q]; | |
617 if (queueItem) { | |
618 output += queueItem[0] + "=" + queueItem[1] + ", "; | |
619 } | |
620 } | |
621 return output; | |
622 }, | |
623 | |
624 /** | |
625 * Sets all properties to null, unsubscribes all listeners from each | |
626 * property's change event and all listeners from the configChangedEvent. | |
627 * @method destroy | |
628 */ | |
629 destroy: function () { | |
630 | |
631 var oConfig = this.config, | |
632 sProperty, | |
633 oProperty; | |
634 | |
635 | |
636 for (sProperty in oConfig) { | |
637 | |
638 if (Lang.hasOwnProperty(oConfig, sProperty)) { | |
639 | |
640 oProperty = oConfig[sProperty]; | |
641 | |
642 oProperty.event.unsubscribeAll(); | |
643 oProperty.event = null; | |
644 | |
645 } | |
646 | |
647 } | |
648 | |
649 this.configChangedEvent.unsubscribeAll(); | |
650 | |
651 this.configChangedEvent = null; | |
652 this.owner = null; | |
653 this.config = null; | |
654 this.initialConfig = null; | |
655 this.eventQueue = null; | |
656 | |
657 } | |
658 | |
659 }; | |
660 | |
661 | |
662 | |
663 /** | |
664 * Checks to determine if a particular function/Object pair are already | |
665 * subscribed to the specified CustomEvent | |
666 * @method YAHOO.util.Config.alreadySubscribed | |
667 * @static | |
668 * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check | |
669 * the subscriptions | |
670 * @param {Function} fn The function to look for in the subscribers list | |
671 * @param {Object} obj The execution scope Object for the subscription | |
672 * @return {Boolean} true, if the function/Object pair is already subscribed | |
673 * to the CustomEvent passed in | |
674 */ | |
675 Config.alreadySubscribed = function (evt, fn, obj) { | |
676 | |
677 var nSubscribers = evt.subscribers.length, | |
678 subsc, | |
679 i; | |
680 | |
681 if (nSubscribers > 0) { | |
682 i = nSubscribers - 1; | |
683 do { | |
684 subsc = evt.subscribers[i]; | |
685 if (subsc && subsc.obj == obj && subsc.fn == fn) { | |
686 return true; | |
687 } | |
688 } | |
689 while (i--); | |
690 } | |
691 | |
692 return false; | |
693 | |
694 }; | |
695 | |
696 YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider); | |
697 | |
698 }()); | |
699 /** | |
700 * The datemath module provides utility methods for basic JavaScript Date object manipulation and | |
701 * comparison. | |
702 * | |
703 * @module datemath | |
704 */ | |
705 | |
706 /** | |
707 * YAHOO.widget.DateMath is used for simple date manipulation. The class is a static utility | |
708 * used for adding, subtracting, and comparing dates. | |
709 * @namespace YAHOO.widget | |
710 * @class DateMath | |
711 */ | |
712 YAHOO.widget.DateMath = { | |
713 /** | |
714 * Constant field representing Day | |
715 * @property DAY | |
716 * @static | |
717 * @final | |
718 * @type String | |
719 */ | |
720 DAY : "D", | |
721 | |
722 /** | |
723 * Constant field representing Week | |
724 * @property WEEK | |
725 * @static | |
726 * @final | |
727 * @type String | |
728 */ | |
729 WEEK : "W", | |
730 | |
731 /** | |
732 * Constant field representing Year | |
733 * @property YEAR | |
734 * @static | |
735 * @final | |
736 * @type String | |
737 */ | |
738 YEAR : "Y", | |
739 | |
740 /** | |
741 * Constant field representing Month | |
742 * @property MONTH | |
743 * @static | |
744 * @final | |
745 * @type String | |
746 */ | |
747 MONTH : "M", | |
748 | |
749 /** | |
750 * Constant field representing one day, in milliseconds | |
751 * @property ONE_DAY_MS | |
752 * @static | |
753 * @final | |
754 * @type Number | |
755 */ | |
756 ONE_DAY_MS : 1000*60*60*24, | |
757 | |
758 /** | |
759 * Constant field representing the date in first week of January | |
760 * which identifies the first week of the year. | |
761 * <p> | |
762 * In the U.S, Jan 1st is normally used based on a Sunday start of week. | |
763 * ISO 8601, used widely throughout Europe, uses Jan 4th, based on a Monday start of week. | |
764 * </p> | |
765 * @property WEEK_ONE_JAN_DATE | |
766 * @static | |
767 * @type Number | |
768 */ | |
769 WEEK_ONE_JAN_DATE : 1, | |
770 | |
771 /** | |
772 * Adds the specified amount of time to the this instance. | |
773 * @method add | |
774 * @param {Date} date The JavaScript Date object to perform addition on | |
775 * @param {String} field The field constant to be used for performing addition. | |
776 * @param {Number} amount The number of units (measured in the field constant) to add to the date. | |
777 * @return {Date} The resulting Date object | |
778 */ | |
779 add : function(date, field, amount) { | |
780 var d = new Date(date.getTime()); | |
781 switch (field) { | |
782 case this.MONTH: | |
783 var newMonth = date.getMonth() + amount; | |
784 var years = 0; | |
785 | |
786 if (newMonth < 0) { | |
787 while (newMonth < 0) { | |
788 newMonth += 12; | |
789 years -= 1; | |
790 } | |
791 } else if (newMonth > 11) { | |
792 while (newMonth > 11) { | |
793 newMonth -= 12; | |
794 years += 1; | |
795 } | |
796 } | |
797 | |
798 d.setMonth(newMonth); | |
799 d.setFullYear(date.getFullYear() + years); | |
800 break; | |
801 case this.DAY: | |
802 this._addDays(d, amount); | |
803 // d.setDate(date.getDate() + amount); | |
804 break; | |
805 case this.YEAR: | |
806 d.setFullYear(date.getFullYear() + amount); | |
807 break; | |
808 case this.WEEK: | |
809 this._addDays(d, (amount * 7)); | |
810 // d.setDate(date.getDate() + (amount * 7)); | |
811 break; | |
812 } | |
813 return d; | |
814 }, | |
815 | |
816 /** | |
817 * Private helper method to account for bug in Safari 2 (webkit < 420) | |
818 * when Date.setDate(n) is called with n less than -128 or greater than 127. | |
819 * <p> | |
820 * Fix approach and original findings are available here: | |
821 * http://brianary.blogspot.com/2006/03/safari-date-bug.html | |
822 * </p> | |
823 * @method _addDays | |
824 * @param {Date} d JavaScript date object | |
825 * @param {Number} nDays The number of days to add to the date object (can be negative) | |
826 * @private | |
827 */ | |
828 _addDays : function(d, nDays) { | |
829 if (YAHOO.env.ua.webkit && YAHOO.env.ua.webkit < 420) { | |
830 if (nDays < 0) { | |
831 // Ensure we don't go below -128 (getDate() is always 1 to 31, so we won't go above 127) | |
832 for(var min = -128; nDays < min; nDays -= min) { | |
833 d.setDate(d.getDate() + min); | |
834 } | |
835 } else { | |
836 // Ensure we don't go above 96 + 31 = 127 | |
837 for(var max = 96; nDays > max; nDays -= max) { | |
838 d.setDate(d.getDate() + max); | |
839 } | |
840 } | |
841 // nDays should be remainder between -128 and 96 | |
842 } | |
843 d.setDate(d.getDate() + nDays); | |
844 }, | |
845 | |
846 /** | |
847 * Subtracts the specified amount of time from the this instance. | |
848 * @method subtract | |
849 * @param {Date} date The JavaScript Date object to perform subtraction on | |
850 * @param {Number} field The this field constant to be used for performing subtraction. | |
851 * @param {Number} amount The number of units (measured in the field constant) to subtract from the date. | |
852 * @return {Date} The resulting Date object | |
853 */ | |
854 subtract : function(date, field, amount) { | |
855 return this.add(date, field, (amount*-1)); | |
856 }, | |
857 | |
858 /** | |
859 * Determines whether a given date is before another date on the calendar. | |
860 * @method before | |
861 * @param {Date} date The Date object to compare with the compare argument | |
862 * @param {Date} compareTo The Date object to use for the comparison | |
863 * @return {Boolean} true if the date occurs before the compared date; false if not. | |
864 */ | |
865 before : function(date, compareTo) { | |
866 var ms = compareTo.getTime(); | |
867 if (date.getTime() < ms) { | |
868 return true; | |
869 } else { | |
870 return false; | |
871 } | |
872 }, | |
873 | |
874 /** | |
875 * Determines whether a given date is after another date on the calendar. | |
876 * @method after | |
877 * @param {Date} date The Date object to compare with the compare argument | |
878 * @param {Date} compareTo The Date object to use for the comparison | |
879 * @return {Boolean} true if the date occurs after the compared date; false if not. | |
880 */ | |
881 after : function(date, compareTo) { | |
882 var ms = compareTo.getTime(); | |
883 if (date.getTime() > ms) { | |
884 return true; | |
885 } else { | |
886 return false; | |
887 } | |
888 }, | |
889 | |
890 /** | |
891 * Determines whether a given date is between two other dates on the calendar. | |
892 * @method between | |
893 * @param {Date} date The date to check for | |
894 * @param {Date} dateBegin The start of the range | |
895 * @param {Date} dateEnd The end of the range | |
896 * @return {Boolean} true if the date occurs between the compared dates; false if not. | |
897 */ | |
898 between : function(date, dateBegin, dateEnd) { | |
899 if (this.after(date, dateBegin) && this.before(date, dateEnd)) { | |
900 return true; | |
901 } else { | |
902 return false; | |
903 } | |
904 }, | |
905 | |
906 /** | |
907 * Retrieves a JavaScript Date object representing January 1 of any given year. | |
908 * @method getJan1 | |
909 * @param {Number} calendarYear The calendar year for which to retrieve January 1 | |
910 * @return {Date} January 1 of the calendar year specified. | |
911 */ | |
912 getJan1 : function(calendarYear) { | |
913 return this.getDate(calendarYear,0,1); | |
914 }, | |
915 | |
916 /** | |
917 * Calculates the number of days the specified date is from January 1 of the specified calendar year. | |
918 * Passing January 1 to this function would return an offset value of zero. | |
919 * @method getDayOffset | |
920 * @param {Date} date The JavaScript date for which to find the offset | |
921 * @param {Number} calendarYear The calendar year to use for determining the offset | |
922 * @return {Number} The number of days since January 1 of the given year | |
923 */ | |
924 getDayOffset : function(date, calendarYear) { | |
925 var beginYear = this.getJan1(calendarYear); // Find the start of the year. This will be in week 1. | |
926 | |
927 // Find the number of days the passed in date is away from the calendar year start | |
928 var dayOffset = Math.ceil((date.getTime()-beginYear.getTime()) / this.ONE_DAY_MS); | |
929 return dayOffset; | |
930 }, | |
931 | |
932 /** | |
933 * Calculates the week number for the given date. Can currently support standard | |
934 * U.S. week numbers, based on Jan 1st defining the 1st week of the year, and | |
935 * ISO8601 week numbers, based on Jan 4th defining the 1st week of the year. | |
936 * | |
937 * @method getWeekNumber | |
938 * @param {Date} date The JavaScript date for which to find the week number | |
939 * @param {Number} firstDayOfWeek The index of the first day of the week (0 = Sun, 1 = Mon ... 6 = Sat). | |
940 * Defaults to 0 | |
941 * @param {Number} janDate The date in the first week of January which defines week one for the year | |
942 * Defaults to the value of YAHOO.widget.DateMath.WEEK_ONE_JAN_DATE, which is 1 (Jan 1st). | |
943 * For the U.S, this is normally Jan 1st. ISO8601 uses Jan 4th to define the first week of the year. | |
944 * | |
945 * @return {Number} The number of the week containing the given date. | |
946 */ | |
947 getWeekNumber : function(date, firstDayOfWeek, janDate) { | |
948 | |
949 // Setup Defaults | |
950 firstDayOfWeek = firstDayOfWeek || 0; | |
951 janDate = janDate || this.WEEK_ONE_JAN_DATE; | |
952 | |
953 var targetDate = this.clearTime(date), | |
954 startOfWeek, | |
955 endOfWeek; | |
956 | |
957 if (targetDate.getDay() === firstDayOfWeek) { | |
958 startOfWeek = targetDate; | |
959 } else { | |
960 startOfWeek = this.getFirstDayOfWeek(targetDate, firstDayOfWeek); | |
961 } | |
962 | |
963 var startYear = startOfWeek.getFullYear(); | |
964 | |
965 // DST shouldn't be a problem here, math is quicker than setDate(); | |
966 endOfWeek = new Date(startOfWeek.getTime() + 6*this.ONE_DAY_MS); | |
967 | |
968 var weekNum; | |
969 if (startYear !== endOfWeek.getFullYear() && endOfWeek.getDate() >= janDate) { | |
970 // If years don't match, endOfWeek is in Jan. and if the | |
971 // week has WEEK_ONE_JAN_DATE in it, it's week one by definition. | |
972 weekNum = 1; | |
973 } else { | |
974 // Get the 1st day of the 1st week, and | |
975 // find how many days away we are from it. | |
976 var weekOne = this.clearTime(this.getDate(startYear, 0, janDate)), | |
977 weekOneDayOne = this.getFirstDayOfWeek(weekOne, firstDayOfWeek); | |
978 | |
979 // Round days to smoothen out 1 hr DST diff | |
980 var daysDiff = Math.round((targetDate.getTime() - weekOneDayOne.getTime())/this.ONE_DAY_MS); | |
981 | |
982 // Calc. Full Weeks | |
983 var rem = daysDiff % 7; | |
984 var weeksDiff = (daysDiff - rem)/7; | |
985 weekNum = weeksDiff + 1; | |
986 } | |
987 return weekNum; | |
988 }, | |
989 | |
990 /** | |
991 * Get the first day of the week, for the give date. | |
992 * @param {Date} dt The date in the week for which the first day is required. | |
993 * @param {Number} startOfWeek The index for the first day of the week, 0 = Sun, 1 = Mon ... 6 = Sat (defaults to 0) | |
994 * @return {Date} The first day of the week | |
995 */ | |
996 getFirstDayOfWeek : function (dt, startOfWeek) { | |
997 startOfWeek = startOfWeek || 0; | |
998 var dayOfWeekIndex = dt.getDay(), | |
999 dayOfWeek = (dayOfWeekIndex - startOfWeek + 7) % 7; | |
1000 | |
1001 return this.subtract(dt, this.DAY, dayOfWeek); | |
1002 }, | |
1003 | |
1004 /** | |
1005 * Determines if a given week overlaps two different years. | |
1006 * @method isYearOverlapWeek | |
1007 * @param {Date} weekBeginDate The JavaScript Date representing the first day of the week. | |
1008 * @return {Boolean} true if the date overlaps two different years. | |
1009 */ | |
1010 isYearOverlapWeek : function(weekBeginDate) { | |
1011 var overlaps = false; | |
1012 var nextWeek = this.add(weekBeginDate, this.DAY, 6); | |
1013 if (nextWeek.getFullYear() != weekBeginDate.getFullYear()) { | |
1014 overlaps = true; | |
1015 } | |
1016 return overlaps; | |
1017 }, | |
1018 | |
1019 /** | |
1020 * Determines if a given week overlaps two different months. | |
1021 * @method isMonthOverlapWeek | |
1022 * @param {Date} weekBeginDate The JavaScript Date representing the first day of the week. | |
1023 * @return {Boolean} true if the date overlaps two different months. | |
1024 */ | |
1025 isMonthOverlapWeek : function(weekBeginDate) { | |
1026 var overlaps = false; | |
1027 var nextWeek = this.add(weekBeginDate, this.DAY, 6); | |
1028 if (nextWeek.getMonth() != weekBeginDate.getMonth()) { | |
1029 overlaps = true; | |
1030 } | |
1031 return overlaps; | |
1032 }, | |
1033 | |
1034 /** | |
1035 * Gets the first day of a month containing a given date. | |
1036 * @method findMonthStart | |
1037 * @param {Date} date The JavaScript Date used to calculate the month start | |
1038 * @return {Date} The JavaScript Date representing the first day of the month | |
1039 */ | |
1040 findMonthStart : function(date) { | |
1041 var start = this.getDate(date.getFullYear(), date.getMonth(), 1); | |
1042 return start; | |
1043 }, | |
1044 | |
1045 /** | |
1046 * Gets the last day of a month containing a given date. | |
1047 * @method findMonthEnd | |
1048 * @param {Date} date The JavaScript Date used to calculate the month end | |
1049 * @return {Date} The JavaScript Date representing the last day of the month | |
1050 */ | |
1051 findMonthEnd : function(date) { | |
1052 var start = this.findMonthStart(date); | |
1053 var nextMonth = this.add(start, this.MONTH, 1); | |
1054 var end = this.subtract(nextMonth, this.DAY, 1); | |
1055 return end; | |
1056 }, | |
1057 | |
1058 /** | |
1059 * Clears the time fields from a given date, effectively setting the time to 12 noon. | |
1060 * @method clearTime | |
1061 * @param {Date} date The JavaScript Date for which the time fields will be cleared | |
1062 * @return {Date} The JavaScript Date cleared of all time fields | |
1063 */ | |
1064 clearTime : function(date) { | |
1065 date.setHours(12,0,0,0); | |
1066 return date; | |
1067 }, | |
1068 | |
1069 /** | |
1070 * Returns a new JavaScript Date object, representing the given year, month and date. Time fields (hr, min, sec, ms) on the new Date object | |
1071 * 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 | |
1072 * set the year to 19xx if a year (xx) which is less than 100 is provided. | |
1073 * <p> | |
1074 * <em>NOTE:</em>Validation on argument values is not performed. It is the caller's responsibility to ensure | |
1075 * arguments are valid as per the ECMAScript-262 Date object specification for the new Date(year, month[, date]) constructor. | |
1076 * </p> | |
1077 * @method getDate | |
1078 * @param {Number} y Year. | |
1079 * @param {Number} m Month index from 0 (Jan) to 11 (Dec). | |
1080 * @param {Number} d (optional) Date from 1 to 31. If not provided, defaults to 1. | |
1081 * @return {Date} The JavaScript date object with year, month, date set as provided. | |
1082 */ | |
1083 getDate : function(y, m, d) { | |
1084 var dt = null; | |
1085 if (YAHOO.lang.isUndefined(d)) { | |
1086 d = 1; | |
1087 } | |
1088 if (y >= 100) { | |
1089 dt = new Date(y, m, d); | |
1090 } else { | |
1091 dt = new Date(); | |
1092 dt.setFullYear(y); | |
1093 dt.setMonth(m); | |
1094 dt.setDate(d); | |
1095 dt.setHours(0,0,0,0); | |
1096 } | |
1097 return dt; | |
1098 } | |
1099 }; | |
1100 /** | |
1101 * 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 | |
1102 * multi-month interface. Calendars are generated entirely via script and can be navigated without any page refreshes. | |
1103 * @module calendar | |
1104 * @title Calendar | |
1105 * @namespace YAHOO.widget | |
1106 * @requires yahoo,dom,event | |
1107 */ | |
1108 (function(){ | |
1109 | |
1110 var Dom = YAHOO.util.Dom, | |
1111 Event = YAHOO.util.Event, | |
1112 Lang = YAHOO.lang, | |
1113 DateMath = YAHOO.widget.DateMath; | |
1114 | |
1115 /** | |
1116 * Calendar is the base class for the Calendar widget. In its most basic | |
1117 * implementation, it has the ability to render a calendar widget on the page | |
1118 * that can be manipulated to select a single date, move back and forth between | |
1119 * months and years. | |
1120 * <p>To construct the placeholder for the calendar widget, the code is as | |
1121 * follows: | |
1122 * <xmp> | |
1123 * <div id="calContainer"></div> | |
1124 * </xmp> | |
1125 * </p> | |
1126 * <p> | |
1127 * <strong>NOTE: As of 2.4.0, the constructor's ID argument is optional.</strong> | |
1128 * The Calendar can be constructed by simply providing a container ID string, | |
1129 * or a reference to a container DIV HTMLElement (the element needs to exist | |
1130 * in the document). | |
1131 * | |
1132 * E.g.: | |
1133 * <xmp> | |
1134 * var c = new YAHOO.widget.Calendar("calContainer", configOptions); | |
1135 * </xmp> | |
1136 * or: | |
1137 * <xmp> | |
1138 * var containerDiv = YAHOO.util.Dom.get("calContainer"); | |
1139 * var c = new YAHOO.widget.Calendar(containerDiv, configOptions); | |
1140 * </xmp> | |
1141 * </p> | |
1142 * <p> | |
1143 * If not provided, the ID will be generated from the container DIV ID by adding an "_t" suffix. | |
1144 * 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". | |
1145 * </p> | |
1146 * | |
1147 * @namespace YAHOO.widget | |
1148 * @class Calendar | |
1149 * @constructor | |
1150 * @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. | |
1151 * @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. | |
1152 * @param {Object} config optional The configuration object containing the initial configuration values for the Calendar. | |
1153 */ | |
1154 function Calendar(id, containerId, config) { | |
1155 this.init.apply(this, arguments); | |
1156 } | |
1157 | |
1158 /** | |
1159 * The path to be used for images loaded for the Calendar | |
1160 * @property YAHOO.widget.Calendar.IMG_ROOT | |
1161 * @static | |
1162 * @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 | |
1163 * @type String | |
1164 */ | |
1165 Calendar.IMG_ROOT = null; | |
1166 | |
1167 /** | |
1168 * Type constant used for renderers to represent an individual date (M/D/Y) | |
1169 * @property YAHOO.widget.Calendar.DATE | |
1170 * @static | |
1171 * @final | |
1172 * @type String | |
1173 */ | |
1174 Calendar.DATE = "D"; | |
1175 | |
1176 /** | |
1177 * Type constant used for renderers to represent an individual date across any year (M/D) | |
1178 * @property YAHOO.widget.Calendar.MONTH_DAY | |
1179 * @static | |
1180 * @final | |
1181 * @type String | |
1182 */ | |
1183 Calendar.MONTH_DAY = "MD"; | |
1184 | |
1185 /** | |
1186 * Type constant used for renderers to represent a weekday | |
1187 * @property YAHOO.widget.Calendar.WEEKDAY | |
1188 * @static | |
1189 * @final | |
1190 * @type String | |
1191 */ | |
1192 Calendar.WEEKDAY = "WD"; | |
1193 | |
1194 /** | |
1195 * Type constant used for renderers to represent a range of individual dates (M/D/Y-M/D/Y) | |
1196 * @property YAHOO.widget.Calendar.RANGE | |
1197 * @static | |
1198 * @final | |
1199 * @type String | |
1200 */ | |
1201 Calendar.RANGE = "R"; | |
1202 | |
1203 /** | |
1204 * Type constant used for renderers to represent a month across any year | |
1205 * @property YAHOO.widget.Calendar.MONTH | |
1206 * @static | |
1207 * @final | |
1208 * @type String | |
1209 */ | |
1210 Calendar.MONTH = "M"; | |
1211 | |
1212 /** | |
1213 * Constant that represents the total number of date cells that are displayed in a given month | |
1214 * @property YAHOO.widget.Calendar.DISPLAY_DAYS | |
1215 * @static | |
1216 * @final | |
1217 * @type Number | |
1218 */ | |
1219 Calendar.DISPLAY_DAYS = 42; | |
1220 | |
1221 /** | |
1222 * Constant used for halting the execution of the remainder of the render stack | |
1223 * @property YAHOO.widget.Calendar.STOP_RENDER | |
1224 * @static | |
1225 * @final | |
1226 * @type String | |
1227 */ | |
1228 Calendar.STOP_RENDER = "S"; | |
1229 | |
1230 /** | |
1231 * Constant used to represent short date field string formats (e.g. Tu or Feb) | |
1232 * @property YAHOO.widget.Calendar.SHORT | |
1233 * @static | |
1234 * @final | |
1235 * @type String | |
1236 */ | |
1237 Calendar.SHORT = "short"; | |
1238 | |
1239 /** | |
1240 * Constant used to represent long date field string formats (e.g. Monday or February) | |
1241 * @property YAHOO.widget.Calendar.LONG | |
1242 * @static | |
1243 * @final | |
1244 * @type String | |
1245 */ | |
1246 Calendar.LONG = "long"; | |
1247 | |
1248 /** | |
1249 * Constant used to represent medium date field string formats (e.g. Mon) | |
1250 * @property YAHOO.widget.Calendar.MEDIUM | |
1251 * @static | |
1252 * @final | |
1253 * @type String | |
1254 */ | |
1255 Calendar.MEDIUM = "medium"; | |
1256 | |
1257 /** | |
1258 * Constant used to represent single character date field string formats (e.g. M, T, W) | |
1259 * @property YAHOO.widget.Calendar.ONE_CHAR | |
1260 * @static | |
1261 * @final | |
1262 * @type String | |
1263 */ | |
1264 Calendar.ONE_CHAR = "1char"; | |
1265 | |
1266 /** | |
1267 * The set of default Config property keys and values for the Calendar. | |
1268 * | |
1269 * <p> | |
1270 * NOTE: This property is made public in order to allow users to change | |
1271 * the default values of configuration properties. Users should not | |
1272 * modify the key string, unless they are overriding the Calendar implementation | |
1273 * </p> | |
1274 * | |
1275 * <p> | |
1276 * The property is an object with key/value pairs, the key being the | |
1277 * uppercase configuration property name and the value being an object | |
1278 * literal with a key string property, and a value property, specifying the | |
1279 * default value of the property. To override a default value, you can set | |
1280 * the value property, for example, <code>YAHOO.widget.Calendar.DEFAULT_CONFIG.MULTI_SELECT.value = true;</code> | |
1281 * | |
1282 * @property YAHOO.widget.Calendar.DEFAULT_CONFIG | |
1283 * @static | |
1284 * @type Object | |
1285 */ | |
1286 | |
1287 Calendar.DEFAULT_CONFIG = { | |
1288 YEAR_OFFSET : {key:"year_offset", value:0, supercedes:["pagedate", "selected", "mindate","maxdate"]}, | |
1289 TODAY : {key:"today", value:new Date(), supercedes:["pagedate"]}, | |
1290 PAGEDATE : {key:"pagedate", value:null}, | |
1291 SELECTED : {key:"selected", value:[]}, | |
1292 TITLE : {key:"title", value:""}, | |
1293 CLOSE : {key:"close", value:false}, | |
1294 IFRAME : {key:"iframe", value:(YAHOO.env.ua.ie && YAHOO.env.ua.ie <= 6) ? true : false}, | |
1295 MINDATE : {key:"mindate", value:null}, | |
1296 MAXDATE : {key:"maxdate", value:null}, | |
1297 MULTI_SELECT : {key:"multi_select", value:false}, | |
1298 START_WEEKDAY : {key:"start_weekday", value:0}, | |
1299 SHOW_WEEKDAYS : {key:"show_weekdays", value:true}, | |
1300 SHOW_WEEK_HEADER : {key:"show_week_header", value:false}, | |
1301 SHOW_WEEK_FOOTER : {key:"show_week_footer", value:false}, | |
1302 HIDE_BLANK_WEEKS : {key:"hide_blank_weeks", value:false}, | |
1303 NAV_ARROW_LEFT: {key:"nav_arrow_left", value:null} , | |
1304 NAV_ARROW_RIGHT : {key:"nav_arrow_right", value:null} , | |
1305 MONTHS_SHORT : {key:"months_short", value:["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]}, | |
1306 MONTHS_LONG: {key:"months_long", value:["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]}, | |
1307 WEEKDAYS_1CHAR: {key:"weekdays_1char", value:["S", "M", "T", "W", "T", "F", "S"]}, | |
1308 WEEKDAYS_SHORT: {key:"weekdays_short", value:["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]}, | |
1309 WEEKDAYS_MEDIUM: {key:"weekdays_medium", value:["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]}, | |
1310 WEEKDAYS_LONG: {key:"weekdays_long", value:["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]}, | |
1311 LOCALE_MONTHS:{key:"locale_months", value:"long"}, | |
1312 LOCALE_WEEKDAYS:{key:"locale_weekdays", value:"short"}, | |
1313 DATE_DELIMITER:{key:"date_delimiter", value:","}, | |
1314 DATE_FIELD_DELIMITER:{key:"date_field_delimiter", value:"/"}, | |
1315 DATE_RANGE_DELIMITER:{key:"date_range_delimiter", value:"-"}, | |
1316 MY_MONTH_POSITION:{key:"my_month_position", value:1}, | |
1317 MY_YEAR_POSITION:{key:"my_year_position", value:2}, | |
1318 MD_MONTH_POSITION:{key:"md_month_position", value:1}, | |
1319 MD_DAY_POSITION:{key:"md_day_position", value:2}, | |
1320 MDY_MONTH_POSITION:{key:"mdy_month_position", value:1}, | |
1321 MDY_DAY_POSITION:{key:"mdy_day_position", value:2}, | |
1322 MDY_YEAR_POSITION:{key:"mdy_year_position", value:3}, | |
1323 MY_LABEL_MONTH_POSITION:{key:"my_label_month_position", value:1}, | |
1324 MY_LABEL_YEAR_POSITION:{key:"my_label_year_position", value:2}, | |
1325 MY_LABEL_MONTH_SUFFIX:{key:"my_label_month_suffix", value:" "}, | |
1326 MY_LABEL_YEAR_SUFFIX:{key:"my_label_year_suffix", value:""}, | |
1327 NAV: {key:"navigator", value: null}, | |
1328 STRINGS : { | |
1329 key:"strings", | |
1330 value: { | |
1331 previousMonth : "Previous Month", | |
1332 nextMonth : "Next Month", | |
1333 close: "Close" | |
1334 }, | |
1335 supercedes : ["close", "title"] | |
1336 } | |
1337 }; | |
1338 | |
1339 /** | |
1340 * The set of default Config property keys and values for the Calendar | |
1341 * @property YAHOO.widget.Calendar._DEFAULT_CONFIG | |
1342 * @deprecated Made public. See the public DEFAULT_CONFIG property for details | |
1343 * @final | |
1344 * @static | |
1345 * @private | |
1346 * @type Object | |
1347 */ | |
1348 Calendar._DEFAULT_CONFIG = Calendar.DEFAULT_CONFIG; | |
1349 | |
1350 var DEF_CFG = Calendar.DEFAULT_CONFIG; | |
1351 | |
1352 /** | |
1353 * The set of Custom Event types supported by the Calendar | |
1354 * @property YAHOO.widget.Calendar._EVENT_TYPES | |
1355 * @final | |
1356 * @static | |
1357 * @private | |
1358 * @type Object | |
1359 */ | |
1360 Calendar._EVENT_TYPES = { | |
1361 BEFORE_SELECT : "beforeSelect", | |
1362 SELECT : "select", | |
1363 BEFORE_DESELECT : "beforeDeselect", | |
1364 DESELECT : "deselect", | |
1365 CHANGE_PAGE : "changePage", | |
1366 BEFORE_RENDER : "beforeRender", | |
1367 RENDER : "render", | |
1368 BEFORE_DESTROY : "beforeDestroy", | |
1369 DESTROY : "destroy", | |
1370 RESET : "reset", | |
1371 CLEAR : "clear", | |
1372 BEFORE_HIDE : "beforeHide", | |
1373 HIDE : "hide", | |
1374 BEFORE_SHOW : "beforeShow", | |
1375 SHOW : "show", | |
1376 BEFORE_HIDE_NAV : "beforeHideNav", | |
1377 HIDE_NAV : "hideNav", | |
1378 BEFORE_SHOW_NAV : "beforeShowNav", | |
1379 SHOW_NAV : "showNav", | |
1380 BEFORE_RENDER_NAV : "beforeRenderNav", | |
1381 RENDER_NAV : "renderNav" | |
1382 }; | |
1383 | |
1384 /** | |
1385 * The set of default style constants for the Calendar | |
1386 * @property YAHOO.widget.Calendar.STYLES | |
1387 * @static | |
1388 * @type Object An object with name/value pairs for the class name identifier/value. | |
1389 */ | |
1390 Calendar.STYLES = { | |
1391 CSS_ROW_HEADER: "calrowhead", | |
1392 CSS_ROW_FOOTER: "calrowfoot", | |
1393 CSS_CELL : "calcell", | |
1394 CSS_CELL_SELECTOR : "selector", | |
1395 CSS_CELL_SELECTED : "selected", | |
1396 CSS_CELL_SELECTABLE : "selectable", | |
1397 CSS_CELL_RESTRICTED : "restricted", | |
1398 CSS_CELL_TODAY : "today", | |
1399 CSS_CELL_OOM : "oom", | |
1400 CSS_CELL_OOB : "previous", | |
1401 CSS_HEADER : "calheader", | |
1402 CSS_HEADER_TEXT : "calhead", | |
1403 CSS_BODY : "calbody", | |
1404 CSS_WEEKDAY_CELL : "calweekdaycell", | |
1405 CSS_WEEKDAY_ROW : "calweekdayrow", | |
1406 CSS_FOOTER : "calfoot", | |
1407 CSS_CALENDAR : "yui-calendar", | |
1408 CSS_SINGLE : "single", | |
1409 CSS_CONTAINER : "yui-calcontainer", | |
1410 CSS_NAV_LEFT : "calnavleft", | |
1411 CSS_NAV_RIGHT : "calnavright", | |
1412 CSS_NAV : "calnav", | |
1413 CSS_CLOSE : "calclose", | |
1414 CSS_CELL_TOP : "calcelltop", | |
1415 CSS_CELL_LEFT : "calcellleft", | |
1416 CSS_CELL_RIGHT : "calcellright", | |
1417 CSS_CELL_BOTTOM : "calcellbottom", | |
1418 CSS_CELL_HOVER : "calcellhover", | |
1419 CSS_CELL_HIGHLIGHT1 : "highlight1", | |
1420 CSS_CELL_HIGHLIGHT2 : "highlight2", | |
1421 CSS_CELL_HIGHLIGHT3 : "highlight3", | |
1422 CSS_CELL_HIGHLIGHT4 : "highlight4", | |
1423 CSS_WITH_TITLE: "withtitle", | |
1424 CSS_FIXED_SIZE: "fixedsize", | |
1425 CSS_LINK_CLOSE: "link-close" | |
1426 }; | |
1427 | |
1428 /** | |
1429 * The set of default style constants for the Calendar | |
1430 * @property YAHOO.widget.Calendar._STYLES | |
1431 * @deprecated Made public. See the public STYLES property for details | |
1432 * @final | |
1433 * @static | |
1434 * @private | |
1435 * @type Object | |
1436 */ | |
1437 Calendar._STYLES = Calendar.STYLES; | |
1438 | |
1439 Calendar.prototype = { | |
1440 | |
1441 /** | |
1442 * The configuration object used to set up the calendars various locale and style options. | |
1443 * @property Config | |
1444 * @private | |
1445 * @deprecated Configuration properties should be set by calling Calendar.cfg.setProperty. | |
1446 * @type Object | |
1447 */ | |
1448 Config : null, | |
1449 | |
1450 /** | |
1451 * The parent CalendarGroup, only to be set explicitly by the parent group | |
1452 * @property parent | |
1453 * @type CalendarGroup | |
1454 */ | |
1455 parent : null, | |
1456 | |
1457 /** | |
1458 * The index of this item in the parent group | |
1459 * @property index | |
1460 * @type Number | |
1461 */ | |
1462 index : -1, | |
1463 | |
1464 /** | |
1465 * The collection of calendar table cells | |
1466 * @property cells | |
1467 * @type HTMLTableCellElement[] | |
1468 */ | |
1469 cells : null, | |
1470 | |
1471 /** | |
1472 * 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]. | |
1473 * @property cellDates | |
1474 * @type Array[](Number[]) | |
1475 */ | |
1476 cellDates : null, | |
1477 | |
1478 /** | |
1479 * The id that uniquely identifies this Calendar. | |
1480 * @property id | |
1481 * @type String | |
1482 */ | |
1483 id : null, | |
1484 | |
1485 /** | |
1486 * The unique id associated with the Calendar's container | |
1487 * @property containerId | |
1488 * @type String | |
1489 */ | |
1490 containerId: null, | |
1491 | |
1492 /** | |
1493 * 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. | |
1494 * @property oDomContainer | |
1495 * @type HTMLElement | |
1496 */ | |
1497 oDomContainer : null, | |
1498 | |
1499 /** | |
1500 * A Date object representing today's date. | |
1501 * @deprecated Use the "today" configuration property | |
1502 * @property today | |
1503 * @type Date | |
1504 */ | |
1505 today : null, | |
1506 | |
1507 /** | |
1508 * The list of render functions, along with required parameters, used to render cells. | |
1509 * @property renderStack | |
1510 * @type Array[] | |
1511 */ | |
1512 renderStack : null, | |
1513 | |
1514 /** | |
1515 * A copy of the initial render functions created before rendering. | |
1516 * @property _renderStack | |
1517 * @private | |
1518 * @type Array | |
1519 */ | |
1520 _renderStack : null, | |
1521 | |
1522 /** | |
1523 * A reference to the CalendarNavigator instance created for this Calendar. | |
1524 * Will be null if the "navigator" configuration property has not been set | |
1525 * @property oNavigator | |
1526 * @type CalendarNavigator | |
1527 */ | |
1528 oNavigator : null, | |
1529 | |
1530 /** | |
1531 * The private list of initially selected dates. | |
1532 * @property _selectedDates | |
1533 * @private | |
1534 * @type Array | |
1535 */ | |
1536 _selectedDates : null, | |
1537 | |
1538 /** | |
1539 * A map of DOM event handlers to attach to cells associated with specific CSS class names | |
1540 * @property domEventMap | |
1541 * @type Object | |
1542 */ | |
1543 domEventMap : null, | |
1544 | |
1545 /** | |
1546 * Protected helper used to parse Calendar constructor/init arguments. | |
1547 * | |
1548 * As of 2.4.0, Calendar supports a simpler constructor | |
1549 * signature. This method reconciles arguments | |
1550 * received in the pre 2.4.0 and 2.4.0 formats. | |
1551 * | |
1552 * @protected | |
1553 * @method _parseArgs | |
1554 * @param {Array} Function "arguments" array | |
1555 * @return {Object} Object with id, container, config properties containing | |
1556 * the reconciled argument values. | |
1557 **/ | |
1558 _parseArgs : function(args) { | |
1559 /* | |
1560 2.4.0 Constructors signatures | |
1561 | |
1562 new Calendar(String) | |
1563 new Calendar(HTMLElement) | |
1564 new Calendar(String, ConfigObject) | |
1565 new Calendar(HTMLElement, ConfigObject) | |
1566 | |
1567 Pre 2.4.0 Constructor signatures | |
1568 | |
1569 new Calendar(String, String) | |
1570 new Calendar(String, HTMLElement) | |
1571 new Calendar(String, String, ConfigObject) | |
1572 new Calendar(String, HTMLElement, ConfigObject) | |
1573 */ | |
1574 var nArgs = {id:null, container:null, config:null}; | |
1575 | |
1576 if (args && args.length && args.length > 0) { | |
1577 switch (args.length) { | |
1578 case 1: | |
1579 nArgs.id = null; | |
1580 nArgs.container = args[0]; | |
1581 nArgs.config = null; | |
1582 break; | |
1583 case 2: | |
1584 if (Lang.isObject(args[1]) && !args[1].tagName && !(args[1] instanceof String)) { | |
1585 nArgs.id = null; | |
1586 nArgs.container = args[0]; | |
1587 nArgs.config = args[1]; | |
1588 } else { | |
1589 nArgs.id = args[0]; | |
1590 nArgs.container = args[1]; | |
1591 nArgs.config = null; | |
1592 } | |
1593 break; | |
1594 default: // 3+ | |
1595 nArgs.id = args[0]; | |
1596 nArgs.container = args[1]; | |
1597 nArgs.config = args[2]; | |
1598 break; | |
1599 } | |
1600 } else { | |
1601 this.logger.log("Invalid constructor/init arguments", "error"); | |
1602 } | |
1603 return nArgs; | |
1604 }, | |
1605 | |
1606 /** | |
1607 * Initializes the Calendar widget. | |
1608 * @method init | |
1609 * | |
1610 * @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. | |
1611 * @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. | |
1612 * @param {Object} config optional The configuration object containing the initial configuration values for the Calendar. | |
1613 */ | |
1614 init : function(id, container, config) { | |
1615 // Normalize 2.4.0, pre 2.4.0 args | |
1616 var nArgs = this._parseArgs(arguments); | |
1617 | |
1618 id = nArgs.id; | |
1619 container = nArgs.container; | |
1620 config = nArgs.config; | |
1621 | |
1622 this.oDomContainer = Dom.get(container); | |
1623 if (!this.oDomContainer) { this.logger.log("Container not found in document.", "error"); } | |
1624 | |
1625 if (!this.oDomContainer.id) { | |
1626 this.oDomContainer.id = Dom.generateId(); | |
1627 } | |
1628 if (!id) { | |
1629 id = this.oDomContainer.id + "_t"; | |
1630 } | |
1631 | |
1632 this.id = id; | |
1633 this.containerId = this.oDomContainer.id; | |
1634 | |
1635 this.logger = new YAHOO.widget.LogWriter("Calendar " + this.id); | |
1636 this.initEvents(); | |
1637 | |
1638 /** | |
1639 * The Config object used to hold the configuration variables for the Calendar | |
1640 * @property cfg | |
1641 * @type YAHOO.util.Config | |
1642 */ | |
1643 this.cfg = new YAHOO.util.Config(this); | |
1644 | |
1645 /** | |
1646 * The local object which contains the Calendar's options | |
1647 * @property Options | |
1648 * @type Object | |
1649 */ | |
1650 this.Options = {}; | |
1651 | |
1652 /** | |
1653 * The local object which contains the Calendar's locale settings | |
1654 * @property Locale | |
1655 * @type Object | |
1656 */ | |
1657 this.Locale = {}; | |
1658 | |
1659 this.initStyles(); | |
1660 | |
1661 Dom.addClass(this.oDomContainer, this.Style.CSS_CONTAINER); | |
1662 Dom.addClass(this.oDomContainer, this.Style.CSS_SINGLE); | |
1663 | |
1664 this.cellDates = []; | |
1665 this.cells = []; | |
1666 this.renderStack = []; | |
1667 this._renderStack = []; | |
1668 | |
1669 this.setupConfig(); | |
1670 | |
1671 if (config) { | |
1672 this.cfg.applyConfig(config, true); | |
1673 } | |
1674 | |
1675 this.cfg.fireQueue(); | |
1676 | |
1677 this.today = this.cfg.getProperty("today"); | |
1678 }, | |
1679 | |
1680 /** | |
1681 * Default Config listener for the iframe property. If the iframe config property is set to true, | |
1682 * renders the built-in IFRAME shim if the container is relatively or absolutely positioned. | |
1683 * | |
1684 * @method configIframe | |
1685 */ | |
1686 configIframe : function(type, args, obj) { | |
1687 var useIframe = args[0]; | |
1688 | |
1689 if (!this.parent) { | |
1690 if (Dom.inDocument(this.oDomContainer)) { | |
1691 if (useIframe) { | |
1692 var pos = Dom.getStyle(this.oDomContainer, "position"); | |
1693 | |
1694 if (pos == "absolute" || pos == "relative") { | |
1695 | |
1696 if (!Dom.inDocument(this.iframe)) { | |
1697 this.iframe = document.createElement("iframe"); | |
1698 this.iframe.src = "javascript:false;"; | |
1699 | |
1700 Dom.setStyle(this.iframe, "opacity", "0"); | |
1701 | |
1702 if (YAHOO.env.ua.ie && YAHOO.env.ua.ie <= 6) { | |
1703 Dom.addClass(this.iframe, this.Style.CSS_FIXED_SIZE); | |
1704 } | |
1705 | |
1706 this.oDomContainer.insertBefore(this.iframe, this.oDomContainer.firstChild); | |
1707 } | |
1708 } | |
1709 } else { | |
1710 if (this.iframe) { | |
1711 if (this.iframe.parentNode) { | |
1712 this.iframe.parentNode.removeChild(this.iframe); | |
1713 } | |
1714 this.iframe = null; | |
1715 } | |
1716 } | |
1717 } | |
1718 } | |
1719 }, | |
1720 | |
1721 /** | |
1722 * Default handler for the "title" property | |
1723 * @method configTitle | |
1724 */ | |
1725 configTitle : function(type, args, obj) { | |
1726 var title = args[0]; | |
1727 | |
1728 // "" disables title bar | |
1729 if (title) { | |
1730 this.createTitleBar(title); | |
1731 } else { | |
1732 var close = this.cfg.getProperty(DEF_CFG.CLOSE.key); | |
1733 if (!close) { | |
1734 this.removeTitleBar(); | |
1735 } else { | |
1736 this.createTitleBar(" "); | |
1737 } | |
1738 } | |
1739 }, | |
1740 | |
1741 /** | |
1742 * Default handler for the "close" property | |
1743 * @method configClose | |
1744 */ | |
1745 configClose : function(type, args, obj) { | |
1746 var close = args[0], | |
1747 title = this.cfg.getProperty(DEF_CFG.TITLE.key); | |
1748 | |
1749 if (close) { | |
1750 if (!title) { | |
1751 this.createTitleBar(" "); | |
1752 } | |
1753 this.createCloseButton(); | |
1754 } else { | |
1755 this.removeCloseButton(); | |
1756 if (!title) { | |
1757 this.removeTitleBar(); | |
1758 } | |
1759 } | |
1760 }, | |
1761 | |
1762 /** | |
1763 * Initializes Calendar's built-in CustomEvents | |
1764 * @method initEvents | |
1765 */ | |
1766 initEvents : function() { | |
1767 | |
1768 var defEvents = Calendar._EVENT_TYPES, | |
1769 CE = YAHOO.util.CustomEvent, | |
1770 cal = this; // To help with minification | |
1771 | |
1772 /** | |
1773 * Fired before a date selection is made | |
1774 * @event beforeSelectEvent | |
1775 */ | |
1776 cal.beforeSelectEvent = new CE(defEvents.BEFORE_SELECT); | |
1777 | |
1778 /** | |
1779 * Fired when a date selection is made | |
1780 * @event selectEvent | |
1781 * @param {Array} Array of Date field arrays in the format [YYYY, MM, DD]. | |
1782 */ | |
1783 cal.selectEvent = new CE(defEvents.SELECT); | |
1784 | |
1785 /** | |
1786 * Fired before a date or set of dates is deselected | |
1787 * @event beforeDeselectEvent | |
1788 */ | |
1789 cal.beforeDeselectEvent = new CE(defEvents.BEFORE_DESELECT); | |
1790 | |
1791 /** | |
1792 * Fired when a date or set of dates is deselected | |
1793 * @event deselectEvent | |
1794 * @param {Array} Array of Date field arrays in the format [YYYY, MM, DD]. | |
1795 */ | |
1796 cal.deselectEvent = new CE(defEvents.DESELECT); | |
1797 | |
1798 /** | |
1799 * Fired when the Calendar page is changed | |
1800 * @event changePageEvent | |
1801 * @param {Date} prevDate The date before the page was changed | |
1802 * @param {Date} newDate The date after the page was changed | |
1803 */ | |
1804 cal.changePageEvent = new CE(defEvents.CHANGE_PAGE); | |
1805 | |
1806 /** | |
1807 * Fired before the Calendar is rendered | |
1808 * @event beforeRenderEvent | |
1809 */ | |
1810 cal.beforeRenderEvent = new CE(defEvents.BEFORE_RENDER); | |
1811 | |
1812 /** | |
1813 * Fired when the Calendar is rendered | |
1814 * @event renderEvent | |
1815 */ | |
1816 cal.renderEvent = new CE(defEvents.RENDER); | |
1817 | |
1818 /** | |
1819 * Fired just before the Calendar is to be destroyed | |
1820 * @event beforeDestroyEvent | |
1821 */ | |
1822 cal.beforeDestroyEvent = new CE(defEvents.BEFORE_DESTROY); | |
1823 | |
1824 /** | |
1825 * Fired after the Calendar is destroyed. This event should be used | |
1826 * for notification only. When this event is fired, important Calendar instance | |
1827 * properties, dom references and event listeners have already been | |
1828 * removed/dereferenced, and hence the Calendar instance is not in a usable | |
1829 * state. | |
1830 * | |
1831 * @event destroyEvent | |
1832 */ | |
1833 cal.destroyEvent = new CE(defEvents.DESTROY); | |
1834 | |
1835 /** | |
1836 * Fired when the Calendar is reset | |
1837 * @event resetEvent | |
1838 */ | |
1839 cal.resetEvent = new CE(defEvents.RESET); | |
1840 | |
1841 /** | |
1842 * Fired when the Calendar is cleared | |
1843 * @event clearEvent | |
1844 */ | |
1845 cal.clearEvent = new CE(defEvents.CLEAR); | |
1846 | |
1847 /** | |
1848 * Fired just before the Calendar is to be shown | |
1849 * @event beforeShowEvent | |
1850 */ | |
1851 cal.beforeShowEvent = new CE(defEvents.BEFORE_SHOW); | |
1852 | |
1853 /** | |
1854 * Fired after the Calendar is shown | |
1855 * @event showEvent | |
1856 */ | |
1857 cal.showEvent = new CE(defEvents.SHOW); | |
1858 | |
1859 /** | |
1860 * Fired just before the Calendar is to be hidden | |
1861 * @event beforeHideEvent | |
1862 */ | |
1863 cal.beforeHideEvent = new CE(defEvents.BEFORE_HIDE); | |
1864 | |
1865 /** | |
1866 * Fired after the Calendar is hidden | |
1867 * @event hideEvent | |
1868 */ | |
1869 cal.hideEvent = new CE(defEvents.HIDE); | |
1870 | |
1871 /** | |
1872 * Fired just before the CalendarNavigator is to be shown | |
1873 * @event beforeShowNavEvent | |
1874 */ | |
1875 cal.beforeShowNavEvent = new CE(defEvents.BEFORE_SHOW_NAV); | |
1876 | |
1877 /** | |
1878 * Fired after the CalendarNavigator is shown | |
1879 * @event showNavEvent | |
1880 */ | |
1881 cal.showNavEvent = new CE(defEvents.SHOW_NAV); | |
1882 | |
1883 /** | |
1884 * Fired just before the CalendarNavigator is to be hidden | |
1885 * @event beforeHideNavEvent | |
1886 */ | |
1887 cal.beforeHideNavEvent = new CE(defEvents.BEFORE_HIDE_NAV); | |
1888 | |
1889 /** | |
1890 * Fired after the CalendarNavigator is hidden | |
1891 * @event hideNavEvent | |
1892 */ | |
1893 cal.hideNavEvent = new CE(defEvents.HIDE_NAV); | |
1894 | |
1895 /** | |
1896 * Fired just before the CalendarNavigator is to be rendered | |
1897 * @event beforeRenderNavEvent | |
1898 */ | |
1899 cal.beforeRenderNavEvent = new CE(defEvents.BEFORE_RENDER_NAV); | |
1900 | |
1901 /** | |
1902 * Fired after the CalendarNavigator is rendered | |
1903 * @event renderNavEvent | |
1904 */ | |
1905 cal.renderNavEvent = new CE(defEvents.RENDER_NAV); | |
1906 | |
1907 cal.beforeSelectEvent.subscribe(cal.onBeforeSelect, this, true); | |
1908 cal.selectEvent.subscribe(cal.onSelect, this, true); | |
1909 cal.beforeDeselectEvent.subscribe(cal.onBeforeDeselect, this, true); | |
1910 cal.deselectEvent.subscribe(cal.onDeselect, this, true); | |
1911 cal.changePageEvent.subscribe(cal.onChangePage, this, true); | |
1912 cal.renderEvent.subscribe(cal.onRender, this, true); | |
1913 cal.resetEvent.subscribe(cal.onReset, this, true); | |
1914 cal.clearEvent.subscribe(cal.onClear, this, true); | |
1915 }, | |
1916 | |
1917 /** | |
1918 * The default event handler for clicks on the "Previous Month" navigation UI | |
1919 * | |
1920 * @method doPreviousMonthNav | |
1921 * @param {DOMEvent} e The DOM event | |
1922 * @param {Calendar} cal A reference to the calendar | |
1923 */ | |
1924 doPreviousMonthNav : function(e, cal) { | |
1925 Event.preventDefault(e); | |
1926 // previousMonth invoked in a timeout, to allow | |
1927 // event to bubble up, with correct target. Calling | |
1928 // previousMonth, will call render which will remove | |
1929 // HTML which generated the event, resulting in an | |
1930 // invalid event target in certain browsers. | |
1931 setTimeout(function() { | |
1932 cal.previousMonth(); | |
1933 var navs = Dom.getElementsByClassName(cal.Style.CSS_NAV_LEFT, "a", cal.oDomContainer); | |
1934 if (navs && navs[0]) { | |
1935 try { | |
1936 navs[0].focus(); | |
1937 } catch (ex) { | |
1938 // ignore | |
1939 } | |
1940 } | |
1941 }, 0); | |
1942 }, | |
1943 | |
1944 /** | |
1945 * The default event handler for clicks on the "Next Month" navigation UI | |
1946 * | |
1947 * @method doNextMonthNav | |
1948 * @param {DOMEvent} e The DOM event | |
1949 * @param {Calendar} cal A reference to the calendar | |
1950 */ | |
1951 doNextMonthNav : function(e, cal) { | |
1952 Event.preventDefault(e); | |
1953 setTimeout(function() { | |
1954 cal.nextMonth(); | |
1955 var navs = Dom.getElementsByClassName(cal.Style.CSS_NAV_RIGHT, "a", cal.oDomContainer); | |
1956 if (navs && navs[0]) { | |
1957 try { | |
1958 navs[0].focus(); | |
1959 } catch (ex) { | |
1960 // ignore | |
1961 } | |
1962 } | |
1963 }, 0); | |
1964 }, | |
1965 | |
1966 /** | |
1967 * The default event handler for date cell selection. Currently attached to | |
1968 * the Calendar's bounding box, referenced by it's <a href="#property_oDomContainer">oDomContainer</a> property. | |
1969 * | |
1970 * @method doSelectCell | |
1971 * @param {DOMEvent} e The DOM event | |
1972 * @param {Calendar} cal A reference to the calendar | |
1973 */ | |
1974 doSelectCell : function(e, cal) { | |
1975 var cell, d, date, index; | |
1976 | |
1977 var target = Event.getTarget(e), | |
1978 tagName = target.tagName.toLowerCase(), | |
1979 defSelector = false; | |
1980 | |
1981 while (tagName != "td" && !Dom.hasClass(target, cal.Style.CSS_CELL_SELECTABLE)) { | |
1982 | |
1983 if (!defSelector && tagName == "a" && Dom.hasClass(target, cal.Style.CSS_CELL_SELECTOR)) { | |
1984 defSelector = true; | |
1985 } | |
1986 | |
1987 target = target.parentNode; | |
1988 tagName = target.tagName.toLowerCase(); | |
1989 | |
1990 if (target == this.oDomContainer || tagName == "html") { | |
1991 return; | |
1992 } | |
1993 } | |
1994 | |
1995 if (defSelector) { | |
1996 // Stop link href navigation for default renderer | |
1997 Event.preventDefault(e); | |
1998 } | |
1999 | |
2000 cell = target; | |
2001 | |
2002 if (Dom.hasClass(cell, cal.Style.CSS_CELL_SELECTABLE)) { | |
2003 index = cal.getIndexFromId(cell.id); | |
2004 if (index > -1) { | |
2005 d = cal.cellDates[index]; | |
2006 if (d) { | |
2007 date = DateMath.getDate(d[0],d[1]-1,d[2]); | |
2008 | |
2009 var link; | |
2010 | |
2011 cal.logger.log("Selecting cell " + index + " via click", "info"); | |
2012 if (cal.Options.MULTI_SELECT) { | |
2013 link = cell.getElementsByTagName("a")[0]; | |
2014 if (link) { | |
2015 link.blur(); | |
2016 } | |
2017 | |
2018 var cellDate = cal.cellDates[index]; | |
2019 var cellDateIndex = cal._indexOfSelectedFieldArray(cellDate); | |
2020 | |
2021 if (cellDateIndex > -1) { | |
2022 cal.deselectCell(index); | |
2023 } else { | |
2024 cal.selectCell(index); | |
2025 } | |
2026 | |
2027 } else { | |
2028 link = cell.getElementsByTagName("a")[0]; | |
2029 if (link) { | |
2030 link.blur(); | |
2031 } | |
2032 cal.selectCell(index); | |
2033 } | |
2034 } | |
2035 } | |
2036 } | |
2037 }, | |
2038 | |
2039 /** | |
2040 * The event that is executed when the user hovers over a cell | |
2041 * @method doCellMouseOver | |
2042 * @param {DOMEvent} e The event | |
2043 * @param {Calendar} cal A reference to the calendar passed by the Event utility | |
2044 */ | |
2045 doCellMouseOver : function(e, cal) { | |
2046 var target; | |
2047 if (e) { | |
2048 target = Event.getTarget(e); | |
2049 } else { | |
2050 target = this; | |
2051 } | |
2052 | |
2053 while (target.tagName && target.tagName.toLowerCase() != "td") { | |
2054 target = target.parentNode; | |
2055 if (!target.tagName || target.tagName.toLowerCase() == "html") { | |
2056 return; | |
2057 } | |
2058 } | |
2059 | |
2060 if (Dom.hasClass(target, cal.Style.CSS_CELL_SELECTABLE)) { | |
2061 Dom.addClass(target, cal.Style.CSS_CELL_HOVER); | |
2062 } | |
2063 }, | |
2064 | |
2065 /** | |
2066 * The event that is executed when the user moves the mouse out of a cell | |
2067 * @method doCellMouseOut | |
2068 * @param {DOMEvent} e The event | |
2069 * @param {Calendar} cal A reference to the calendar passed by the Event utility | |
2070 */ | |
2071 doCellMouseOut : function(e, cal) { | |
2072 var target; | |
2073 if (e) { | |
2074 target = Event.getTarget(e); | |
2075 } else { | |
2076 target = this; | |
2077 } | |
2078 | |
2079 while (target.tagName && target.tagName.toLowerCase() != "td") { | |
2080 target = target.parentNode; | |
2081 if (!target.tagName || target.tagName.toLowerCase() == "html") { | |
2082 return; | |
2083 } | |
2084 } | |
2085 | |
2086 if (Dom.hasClass(target, cal.Style.CSS_CELL_SELECTABLE)) { | |
2087 Dom.removeClass(target, cal.Style.CSS_CELL_HOVER); | |
2088 } | |
2089 }, | |
2090 | |
2091 setupConfig : function() { | |
2092 | |
2093 var cfg = this.cfg; | |
2094 | |
2095 /** | |
2096 * The date to use to represent "Today". | |
2097 * | |
2098 * @config today | |
2099 * @type Date | |
2100 * @default The client side date (new Date()) when the Calendar is instantiated. | |
2101 */ | |
2102 cfg.addProperty(DEF_CFG.TODAY.key, { value: new Date(DEF_CFG.TODAY.value.getTime()), supercedes:DEF_CFG.TODAY.supercedes, handler:this.configToday, suppressEvent:true } ); | |
2103 | |
2104 /** | |
2105 * The month/year representing the current visible Calendar date (mm/yyyy) | |
2106 * @config pagedate | |
2107 * @type String | Date | |
2108 * @default Today's date | |
2109 */ | |
2110 cfg.addProperty(DEF_CFG.PAGEDATE.key, { value: DEF_CFG.PAGEDATE.value || new Date(DEF_CFG.TODAY.value.getTime()), handler:this.configPageDate } ); | |
2111 | |
2112 /** | |
2113 * The date or range of dates representing the current Calendar selection | |
2114 * @config selected | |
2115 * @type String | |
2116 * @default [] | |
2117 */ | |
2118 cfg.addProperty(DEF_CFG.SELECTED.key, { value:DEF_CFG.SELECTED.value.concat(), handler:this.configSelected } ); | |
2119 | |
2120 /** | |
2121 * The title to display above the Calendar's month header | |
2122 * @config title | |
2123 * @type String | |
2124 * @default "" | |
2125 */ | |
2126 cfg.addProperty(DEF_CFG.TITLE.key, { value:DEF_CFG.TITLE.value, handler:this.configTitle } ); | |
2127 | |
2128 /** | |
2129 * Whether or not a close button should be displayed for this Calendar | |
2130 * @config close | |
2131 * @type Boolean | |
2132 * @default false | |
2133 */ | |
2134 cfg.addProperty(DEF_CFG.CLOSE.key, { value:DEF_CFG.CLOSE.value, handler:this.configClose } ); | |
2135 | |
2136 /** | |
2137 * 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. | |
2138 * This property is enabled by default for IE6 and below. It is disabled by default for other browsers for performance reasons, but can be | |
2139 * enabled if required. | |
2140 * | |
2141 * @config iframe | |
2142 * @type Boolean | |
2143 * @default true for IE6 and below, false for all other browsers | |
2144 */ | |
2145 cfg.addProperty(DEF_CFG.IFRAME.key, { value:DEF_CFG.IFRAME.value, handler:this.configIframe, validator:cfg.checkBoolean } ); | |
2146 | |
2147 /** | |
2148 * The minimum selectable date in the current Calendar (mm/dd/yyyy) | |
2149 * @config mindate | |
2150 * @type String | Date | |
2151 * @default null | |
2152 */ | |
2153 cfg.addProperty(DEF_CFG.MINDATE.key, { value:DEF_CFG.MINDATE.value, handler:this.configMinDate } ); | |
2154 | |
2155 /** | |
2156 * The maximum selectable date in the current Calendar (mm/dd/yyyy) | |
2157 * @config maxdate | |
2158 * @type String | Date | |
2159 * @default null | |
2160 */ | |
2161 cfg.addProperty(DEF_CFG.MAXDATE.key, { value:DEF_CFG.MAXDATE.value, handler:this.configMaxDate } ); | |
2162 | |
2163 // Options properties | |
2164 | |
2165 /** | |
2166 * True if the Calendar should allow multiple selections. False by default. | |
2167 * @config MULTI_SELECT | |
2168 * @type Boolean | |
2169 * @default false | |
2170 */ | |
2171 cfg.addProperty(DEF_CFG.MULTI_SELECT.key, { value:DEF_CFG.MULTI_SELECT.value, handler:this.configOptions, validator:cfg.checkBoolean } ); | |
2172 | |
2173 /** | |
2174 * The weekday the week begins on. Default is 0 (Sunday = 0, Monday = 1 ... Saturday = 6). | |
2175 * @config START_WEEKDAY | |
2176 * @type number | |
2177 * @default 0 | |
2178 */ | |
2179 cfg.addProperty(DEF_CFG.START_WEEKDAY.key, { value:DEF_CFG.START_WEEKDAY.value, handler:this.configOptions, validator:cfg.checkNumber } ); | |
2180 | |
2181 /** | |
2182 * True if the Calendar should show weekday labels. True by default. | |
2183 * @config SHOW_WEEKDAYS | |
2184 * @type Boolean | |
2185 * @default true | |
2186 */ | |
2187 cfg.addProperty(DEF_CFG.SHOW_WEEKDAYS.key, { value:DEF_CFG.SHOW_WEEKDAYS.value, handler:this.configOptions, validator:cfg.checkBoolean } ); | |
2188 | |
2189 /** | |
2190 * True if the Calendar should show week row headers. False by default. | |
2191 * @config SHOW_WEEK_HEADER | |
2192 * @type Boolean | |
2193 * @default false | |
2194 */ | |
2195 cfg.addProperty(DEF_CFG.SHOW_WEEK_HEADER.key, { value:DEF_CFG.SHOW_WEEK_HEADER.value, handler:this.configOptions, validator:cfg.checkBoolean } ); | |
2196 | |
2197 /** | |
2198 * True if the Calendar should show week row footers. False by default. | |
2199 * @config SHOW_WEEK_FOOTER | |
2200 * @type Boolean | |
2201 * @default false | |
2202 */ | |
2203 cfg.addProperty(DEF_CFG.SHOW_WEEK_FOOTER.key,{ value:DEF_CFG.SHOW_WEEK_FOOTER.value, handler:this.configOptions, validator:cfg.checkBoolean } ); | |
2204 | |
2205 /** | |
2206 * True if the Calendar should suppress weeks that are not a part of the current month. False by default. | |
2207 * @config HIDE_BLANK_WEEKS | |
2208 * @type Boolean | |
2209 * @default false | |
2210 */ | |
2211 cfg.addProperty(DEF_CFG.HIDE_BLANK_WEEKS.key, { value:DEF_CFG.HIDE_BLANK_WEEKS.value, handler:this.configOptions, validator:cfg.checkBoolean } ); | |
2212 | |
2213 /** | |
2214 * The image that should be used for the left navigation arrow. | |
2215 * @config NAV_ARROW_LEFT | |
2216 * @type String | |
2217 * @deprecated You can customize the image by overriding the default CSS class for the left arrow - "calnavleft" | |
2218 * @default null | |
2219 */ | |
2220 cfg.addProperty(DEF_CFG.NAV_ARROW_LEFT.key, { value:DEF_CFG.NAV_ARROW_LEFT.value, handler:this.configOptions } ); | |
2221 | |
2222 /** | |
2223 * The image that should be used for the right navigation arrow. | |
2224 * @config NAV_ARROW_RIGHT | |
2225 * @type String | |
2226 * @deprecated You can customize the image by overriding the default CSS class for the right arrow - "calnavright" | |
2227 * @default null | |
2228 */ | |
2229 cfg.addProperty(DEF_CFG.NAV_ARROW_RIGHT.key, { value:DEF_CFG.NAV_ARROW_RIGHT.value, handler:this.configOptions } ); | |
2230 | |
2231 // Locale properties | |
2232 | |
2233 /** | |
2234 * The short month labels for the current locale. | |
2235 * @config MONTHS_SHORT | |
2236 * @type String[] | |
2237 * @default ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] | |
2238 */ | |
2239 cfg.addProperty(DEF_CFG.MONTHS_SHORT.key, { value:DEF_CFG.MONTHS_SHORT.value, handler:this.configLocale } ); | |
2240 | |
2241 /** | |
2242 * The long month labels for the current locale. | |
2243 * @config MONTHS_LONG | |
2244 * @type String[] | |
2245 * @default ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" | |
2246 */ | |
2247 cfg.addProperty(DEF_CFG.MONTHS_LONG.key, { value:DEF_CFG.MONTHS_LONG.value, handler:this.configLocale } ); | |
2248 | |
2249 /** | |
2250 * The 1-character weekday labels for the current locale. | |
2251 * @config WEEKDAYS_1CHAR | |
2252 * @type String[] | |
2253 * @default ["S", "M", "T", "W", "T", "F", "S"] | |
2254 */ | |
2255 cfg.addProperty(DEF_CFG.WEEKDAYS_1CHAR.key, { value:DEF_CFG.WEEKDAYS_1CHAR.value, handler:this.configLocale } ); | |
2256 | |
2257 /** | |
2258 * The short weekday labels for the current locale. | |
2259 * @config WEEKDAYS_SHORT | |
2260 * @type String[] | |
2261 * @default ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"] | |
2262 */ | |
2263 cfg.addProperty(DEF_CFG.WEEKDAYS_SHORT.key, { value:DEF_CFG.WEEKDAYS_SHORT.value, handler:this.configLocale } ); | |
2264 | |
2265 /** | |
2266 * The medium weekday labels for the current locale. | |
2267 * @config WEEKDAYS_MEDIUM | |
2268 * @type String[] | |
2269 * @default ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] | |
2270 */ | |
2271 cfg.addProperty(DEF_CFG.WEEKDAYS_MEDIUM.key, { value:DEF_CFG.WEEKDAYS_MEDIUM.value, handler:this.configLocale } ); | |
2272 | |
2273 /** | |
2274 * The long weekday labels for the current locale. | |
2275 * @config WEEKDAYS_LONG | |
2276 * @type String[] | |
2277 * @default ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] | |
2278 */ | |
2279 cfg.addProperty(DEF_CFG.WEEKDAYS_LONG.key, { value:DEF_CFG.WEEKDAYS_LONG.value, handler:this.configLocale } ); | |
2280 | |
2281 /** | |
2282 * Refreshes the locale values used to build the Calendar. | |
2283 * @method refreshLocale | |
2284 * @private | |
2285 */ | |
2286 var refreshLocale = function() { | |
2287 cfg.refireEvent(DEF_CFG.LOCALE_MONTHS.key); | |
2288 cfg.refireEvent(DEF_CFG.LOCALE_WEEKDAYS.key); | |
2289 }; | |
2290 | |
2291 cfg.subscribeToConfigEvent(DEF_CFG.START_WEEKDAY.key, refreshLocale, this, true); | |
2292 cfg.subscribeToConfigEvent(DEF_CFG.MONTHS_SHORT.key, refreshLocale, this, true); | |
2293 cfg.subscribeToConfigEvent(DEF_CFG.MONTHS_LONG.key, refreshLocale, this, true); | |
2294 cfg.subscribeToConfigEvent(DEF_CFG.WEEKDAYS_1CHAR.key, refreshLocale, this, true); | |
2295 cfg.subscribeToConfigEvent(DEF_CFG.WEEKDAYS_SHORT.key, refreshLocale, this, true); | |
2296 cfg.subscribeToConfigEvent(DEF_CFG.WEEKDAYS_MEDIUM.key, refreshLocale, this, true); | |
2297 cfg.subscribeToConfigEvent(DEF_CFG.WEEKDAYS_LONG.key, refreshLocale, this, true); | |
2298 | |
2299 /** | |
2300 * The setting that determines which length of month labels should be used. Possible values are "short" and "long". | |
2301 * @config LOCALE_MONTHS | |
2302 * @type String | |
2303 * @default "long" | |
2304 */ | |
2305 cfg.addProperty(DEF_CFG.LOCALE_MONTHS.key, { value:DEF_CFG.LOCALE_MONTHS.value, handler:this.configLocaleValues } ); | |
2306 | |
2307 /** | |
2308 * The setting that determines which length of weekday labels should be used. Possible values are "1char", "short", "medium", and "long". | |
2309 * @config LOCALE_WEEKDAYS | |
2310 * @type String | |
2311 * @default "short" | |
2312 */ | |
2313 cfg.addProperty(DEF_CFG.LOCALE_WEEKDAYS.key, { value:DEF_CFG.LOCALE_WEEKDAYS.value, handler:this.configLocaleValues } ); | |
2314 | |
2315 /** | |
2316 * The positive or negative year offset from the Gregorian calendar year (assuming a January 1st rollover) to | |
2317 * be used when displaying and parsing dates. NOTE: All JS Date objects returned by methods, or expected as input by | |
2318 * methods will always represent the Gregorian year, in order to maintain date/month/week values. | |
2319 * | |
2320 * @config YEAR_OFFSET | |
2321 * @type Number | |
2322 * @default 0 | |
2323 */ | |
2324 cfg.addProperty(DEF_CFG.YEAR_OFFSET.key, { value:DEF_CFG.YEAR_OFFSET.value, supercedes:DEF_CFG.YEAR_OFFSET.supercedes, handler:this.configLocale } ); | |
2325 | |
2326 /** | |
2327 * The value used to delimit individual dates in a date string passed to various Calendar functions. | |
2328 * @config DATE_DELIMITER | |
2329 * @type String | |
2330 * @default "," | |
2331 */ | |
2332 cfg.addProperty(DEF_CFG.DATE_DELIMITER.key, { value:DEF_CFG.DATE_DELIMITER.value, handler:this.configLocale } ); | |
2333 | |
2334 /** | |
2335 * The value used to delimit date fields in a date string passed to various Calendar functions. | |
2336 * @config DATE_FIELD_DELIMITER | |
2337 * @type String | |
2338 * @default "/" | |
2339 */ | |
2340 cfg.addProperty(DEF_CFG.DATE_FIELD_DELIMITER.key, { value:DEF_CFG.DATE_FIELD_DELIMITER.value, handler:this.configLocale } ); | |
2341 | |
2342 /** | |
2343 * The value used to delimit date ranges in a date string passed to various Calendar functions. | |
2344 * @config DATE_RANGE_DELIMITER | |
2345 * @type String | |
2346 * @default "-" | |
2347 */ | |
2348 cfg.addProperty(DEF_CFG.DATE_RANGE_DELIMITER.key, { value:DEF_CFG.DATE_RANGE_DELIMITER.value, handler:this.configLocale } ); | |
2349 | |
2350 /** | |
2351 * The position of the month in a month/year date string | |
2352 * @config MY_MONTH_POSITION | |
2353 * @type Number | |
2354 * @default 1 | |
2355 */ | |
2356 cfg.addProperty(DEF_CFG.MY_MONTH_POSITION.key, { value:DEF_CFG.MY_MONTH_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } ); | |
2357 | |
2358 /** | |
2359 * The position of the year in a month/year date string | |
2360 * @config MY_YEAR_POSITION | |
2361 * @type Number | |
2362 * @default 2 | |
2363 */ | |
2364 cfg.addProperty(DEF_CFG.MY_YEAR_POSITION.key, { value:DEF_CFG.MY_YEAR_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } ); | |
2365 | |
2366 /** | |
2367 * The position of the month in a month/day date string | |
2368 * @config MD_MONTH_POSITION | |
2369 * @type Number | |
2370 * @default 1 | |
2371 */ | |
2372 cfg.addProperty(DEF_CFG.MD_MONTH_POSITION.key, { value:DEF_CFG.MD_MONTH_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } ); | |
2373 | |
2374 /** | |
2375 * The position of the day in a month/year date string | |
2376 * @config MD_DAY_POSITION | |
2377 * @type Number | |
2378 * @default 2 | |
2379 */ | |
2380 cfg.addProperty(DEF_CFG.MD_DAY_POSITION.key, { value:DEF_CFG.MD_DAY_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } ); | |
2381 | |
2382 /** | |
2383 * The position of the month in a month/day/year date string | |
2384 * @config MDY_MONTH_POSITION | |
2385 * @type Number | |
2386 * @default 1 | |
2387 */ | |
2388 cfg.addProperty(DEF_CFG.MDY_MONTH_POSITION.key, { value:DEF_CFG.MDY_MONTH_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } ); | |
2389 | |
2390 /** | |
2391 * The position of the day in a month/day/year date string | |
2392 * @config MDY_DAY_POSITION | |
2393 * @type Number | |
2394 * @default 2 | |
2395 */ | |
2396 cfg.addProperty(DEF_CFG.MDY_DAY_POSITION.key, { value:DEF_CFG.MDY_DAY_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } ); | |
2397 | |
2398 /** | |
2399 * The position of the year in a month/day/year date string | |
2400 * @config MDY_YEAR_POSITION | |
2401 * @type Number | |
2402 * @default 3 | |
2403 */ | |
2404 cfg.addProperty(DEF_CFG.MDY_YEAR_POSITION.key, { value:DEF_CFG.MDY_YEAR_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } ); | |
2405 | |
2406 /** | |
2407 * The position of the month in the month year label string used as the Calendar header | |
2408 * @config MY_LABEL_MONTH_POSITION | |
2409 * @type Number | |
2410 * @default 1 | |
2411 */ | |
2412 cfg.addProperty(DEF_CFG.MY_LABEL_MONTH_POSITION.key, { value:DEF_CFG.MY_LABEL_MONTH_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } ); | |
2413 | |
2414 /** | |
2415 * The position of the year in the month year label string used as the Calendar header | |
2416 * @config MY_LABEL_YEAR_POSITION | |
2417 * @type Number | |
2418 * @default 2 | |
2419 */ | |
2420 cfg.addProperty(DEF_CFG.MY_LABEL_YEAR_POSITION.key, { value:DEF_CFG.MY_LABEL_YEAR_POSITION.value, handler:this.configLocale, validator:cfg.checkNumber } ); | |
2421 | |
2422 /** | |
2423 * The suffix used after the month when rendering the Calendar header | |
2424 * @config MY_LABEL_MONTH_SUFFIX | |
2425 * @type String | |
2426 * @default " " | |
2427 */ | |
2428 cfg.addProperty(DEF_CFG.MY_LABEL_MONTH_SUFFIX.key, { value:DEF_CFG.MY_LABEL_MONTH_SUFFIX.value, handler:this.configLocale } ); | |
2429 | |
2430 /** | |
2431 * The suffix used after the year when rendering the Calendar header | |
2432 * @config MY_LABEL_YEAR_SUFFIX | |
2433 * @type String | |
2434 * @default "" | |
2435 */ | |
2436 cfg.addProperty(DEF_CFG.MY_LABEL_YEAR_SUFFIX.key, { value:DEF_CFG.MY_LABEL_YEAR_SUFFIX.value, handler:this.configLocale } ); | |
2437 | |
2438 /** | |
2439 * Configuration for the Month/Year CalendarNavigator UI which allows the user to jump directly to a | |
2440 * specific Month/Year without having to scroll sequentially through months. | |
2441 * <p> | |
2442 * Setting this property to null (default value) or false, will disable the CalendarNavigator UI. | |
2443 * </p> | |
2444 * <p> | |
2445 * Setting this property to true will enable the CalendarNavigatior UI with the default CalendarNavigator configuration values. | |
2446 * </p> | |
2447 * <p> | |
2448 * This property can also be set to an object literal containing configuration properties for the CalendarNavigator UI. | |
2449 * The configuration object expects the the following case-sensitive properties, with the "strings" property being a nested object. | |
2450 * Any properties which are not provided will use the default values (defined in the CalendarNavigator class). | |
2451 * </p> | |
2452 * <dl> | |
2453 * <dt>strings</dt> | |
2454 * <dd><em>Object</em> : An object with the properties shown below, defining the string labels to use in the Navigator's UI | |
2455 * <dl> | |
2456 * <dt>month</dt><dd><em>String</em> : The string to use for the month label. Defaults to "Month".</dd> | |
2457 * <dt>year</dt><dd><em>String</em> : The string to use for the year label. Defaults to "Year".</dd> | |
2458 * <dt>submit</dt><dd><em>String</em> : The string to use for the submit button label. Defaults to "Okay".</dd> | |
2459 * <dt>cancel</dt><dd><em>String</em> : The string to use for the cancel button label. Defaults to "Cancel".</dd> | |
2460 * <dt>invalidYear</dt><dd><em>String</em> : The string to use for invalid year values. Defaults to "Year needs to be a number".</dd> | |
2461 * </dl> | |
2462 * </dd> | |
2463 * <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> | |
2464 * <dt>initialFocus</dt><dd><em>String</em> : Either "year" or "month" specifying which input control should get initial focus. Defaults to "year"</dd> | |
2465 * </dl> | |
2466 * <p>E.g.</p> | |
2467 * <pre> | |
2468 * var navConfig = { | |
2469 * strings: { | |
2470 * month:"Calendar Month", | |
2471 * year:"Calendar Year", | |
2472 * submit: "Submit", | |
2473 * cancel: "Cancel", | |
2474 * invalidYear: "Please enter a valid year" | |
2475 * }, | |
2476 * monthFormat: YAHOO.widget.Calendar.SHORT, | |
2477 * initialFocus: "month" | |
2478 * } | |
2479 * </pre> | |
2480 * @config navigator | |
2481 * @type {Object|Boolean} | |
2482 * @default null | |
2483 */ | |
2484 cfg.addProperty(DEF_CFG.NAV.key, { value:DEF_CFG.NAV.value, handler:this.configNavigator } ); | |
2485 | |
2486 /** | |
2487 * The map of UI strings which the Calendar UI uses. | |
2488 * | |
2489 * @config strings | |
2490 * @type {Object} | |
2491 * @default An object with the properties shown below: | |
2492 * <dl> | |
2493 * <dt>previousMonth</dt><dd><em>String</em> : The string to use for the "Previous Month" navigation UI. Defaults to "Previous Month".</dd> | |
2494 * <dt>nextMonth</dt><dd><em>String</em> : The string to use for the "Next Month" navigation UI. Defaults to "Next Month".</dd> | |
2495 * <dt>close</dt><dd><em>String</em> : The string to use for the close button label. Defaults to "Close".</dd> | |
2496 * </dl> | |
2497 */ | |
2498 cfg.addProperty(DEF_CFG.STRINGS.key, { | |
2499 value:DEF_CFG.STRINGS.value, | |
2500 handler:this.configStrings, | |
2501 validator: function(val) { | |
2502 return Lang.isObject(val); | |
2503 }, | |
2504 supercedes:DEF_CFG.STRINGS.supercedes | |
2505 }); | |
2506 }, | |
2507 | |
2508 /** | |
2509 * The default handler for the "strings" property | |
2510 * @method configStrings | |
2511 */ | |
2512 configStrings : function(type, args, obj) { | |
2513 var val = Lang.merge(DEF_CFG.STRINGS.value, args[0]); | |
2514 this.cfg.setProperty(DEF_CFG.STRINGS.key, val, true); | |
2515 }, | |
2516 | |
2517 /** | |
2518 * The default handler for the "pagedate" property | |
2519 * @method configPageDate | |
2520 */ | |
2521 configPageDate : function(type, args, obj) { | |
2522 this.cfg.setProperty(DEF_CFG.PAGEDATE.key, this._parsePageDate(args[0]), true); | |
2523 }, | |
2524 | |
2525 /** | |
2526 * The default handler for the "mindate" property | |
2527 * @method configMinDate | |
2528 */ | |
2529 configMinDate : function(type, args, obj) { | |
2530 var val = args[0]; | |
2531 if (Lang.isString(val)) { | |
2532 val = this._parseDate(val); | |
2533 this.cfg.setProperty(DEF_CFG.MINDATE.key, DateMath.getDate(val[0],(val[1]-1),val[2])); | |
2534 } | |
2535 }, | |
2536 | |
2537 /** | |
2538 * The default handler for the "maxdate" property | |
2539 * @method configMaxDate | |
2540 */ | |
2541 configMaxDate : function(type, args, obj) { | |
2542 var val = args[0]; | |
2543 if (Lang.isString(val)) { | |
2544 val = this._parseDate(val); | |
2545 this.cfg.setProperty(DEF_CFG.MAXDATE.key, DateMath.getDate(val[0],(val[1]-1),val[2])); | |
2546 } | |
2547 }, | |
2548 | |
2549 /** | |
2550 * The default handler for the "today" property | |
2551 * @method configToday | |
2552 */ | |
2553 configToday : function(type, args, obj) { | |
2554 // Only do this for initial set. Changing the today property after the initial | |
2555 // set, doesn't affect pagedate | |
2556 var val = args[0]; | |
2557 if (Lang.isString(val)) { | |
2558 val = this._parseDate(val); | |
2559 } | |
2560 var today = DateMath.clearTime(val); | |
2561 if (!this.cfg.initialConfig[DEF_CFG.PAGEDATE.key]) { | |
2562 this.cfg.setProperty(DEF_CFG.PAGEDATE.key, today); | |
2563 } | |
2564 this.today = today; | |
2565 this.cfg.setProperty(DEF_CFG.TODAY.key, today, true); | |
2566 }, | |
2567 | |
2568 /** | |
2569 * The default handler for the "selected" property | |
2570 * @method configSelected | |
2571 */ | |
2572 configSelected : function(type, args, obj) { | |
2573 var selected = args[0], | |
2574 cfgSelected = DEF_CFG.SELECTED.key; | |
2575 | |
2576 if (selected) { | |
2577 if (Lang.isString(selected)) { | |
2578 this.cfg.setProperty(cfgSelected, this._parseDates(selected), true); | |
2579 } | |
2580 } | |
2581 if (! this._selectedDates) { | |
2582 this._selectedDates = this.cfg.getProperty(cfgSelected); | |
2583 } | |
2584 }, | |
2585 | |
2586 /** | |
2587 * The default handler for all configuration options properties | |
2588 * @method configOptions | |
2589 */ | |
2590 configOptions : function(type, args, obj) { | |
2591 this.Options[type.toUpperCase()] = args[0]; | |
2592 }, | |
2593 | |
2594 /** | |
2595 * The default handler for all configuration locale properties | |
2596 * @method configLocale | |
2597 */ | |
2598 configLocale : function(type, args, obj) { | |
2599 this.Locale[type.toUpperCase()] = args[0]; | |
2600 | |
2601 this.cfg.refireEvent(DEF_CFG.LOCALE_MONTHS.key); | |
2602 this.cfg.refireEvent(DEF_CFG.LOCALE_WEEKDAYS.key); | |
2603 }, | |
2604 | |
2605 /** | |
2606 * The default handler for all configuration locale field length properties | |
2607 * @method configLocaleValues | |
2608 */ | |
2609 configLocaleValues : function(type, args, obj) { | |
2610 | |
2611 type = type.toLowerCase(); | |
2612 | |
2613 var val = args[0], | |
2614 cfg = this.cfg, | |
2615 Locale = this.Locale; | |
2616 | |
2617 switch (type) { | |
2618 case DEF_CFG.LOCALE_MONTHS.key: | |
2619 switch (val) { | |
2620 case Calendar.SHORT: | |
2621 Locale.LOCALE_MONTHS = cfg.getProperty(DEF_CFG.MONTHS_SHORT.key).concat(); | |
2622 break; | |
2623 case Calendar.LONG: | |
2624 Locale.LOCALE_MONTHS = cfg.getProperty(DEF_CFG.MONTHS_LONG.key).concat(); | |
2625 break; | |
2626 } | |
2627 break; | |
2628 case DEF_CFG.LOCALE_WEEKDAYS.key: | |
2629 switch (val) { | |
2630 case Calendar.ONE_CHAR: | |
2631 Locale.LOCALE_WEEKDAYS = cfg.getProperty(DEF_CFG.WEEKDAYS_1CHAR.key).concat(); | |
2632 break; | |
2633 case Calendar.SHORT: | |
2634 Locale.LOCALE_WEEKDAYS = cfg.getProperty(DEF_CFG.WEEKDAYS_SHORT.key).concat(); | |
2635 break; | |
2636 case Calendar.MEDIUM: | |
2637 Locale.LOCALE_WEEKDAYS = cfg.getProperty(DEF_CFG.WEEKDAYS_MEDIUM.key).concat(); | |
2638 break; | |
2639 case Calendar.LONG: | |
2640 Locale.LOCALE_WEEKDAYS = cfg.getProperty(DEF_CFG.WEEKDAYS_LONG.key).concat(); | |
2641 break; | |
2642 } | |
2643 | |
2644 var START_WEEKDAY = cfg.getProperty(DEF_CFG.START_WEEKDAY.key); | |
2645 | |
2646 if (START_WEEKDAY > 0) { | |
2647 for (var w=0; w < START_WEEKDAY; ++w) { | |
2648 Locale.LOCALE_WEEKDAYS.push(Locale.LOCALE_WEEKDAYS.shift()); | |
2649 } | |
2650 } | |
2651 break; | |
2652 } | |
2653 }, | |
2654 | |
2655 /** | |
2656 * The default handler for the "navigator" property | |
2657 * @method configNavigator | |
2658 */ | |
2659 configNavigator : function(type, args, obj) { | |
2660 var val = args[0]; | |
2661 if (YAHOO.widget.CalendarNavigator && (val === true || Lang.isObject(val))) { | |
2662 if (!this.oNavigator) { | |
2663 this.oNavigator = new YAHOO.widget.CalendarNavigator(this); | |
2664 // Cleanup DOM Refs/Events before innerHTML is removed. | |
2665 this.beforeRenderEvent.subscribe(function () { | |
2666 if (!this.pages) { | |
2667 this.oNavigator.erase(); | |
2668 } | |
2669 }, this, true); | |
2670 } | |
2671 } else { | |
2672 if (this.oNavigator) { | |
2673 this.oNavigator.destroy(); | |
2674 this.oNavigator = null; | |
2675 } | |
2676 } | |
2677 }, | |
2678 | |
2679 /** | |
2680 * Defines the style constants for the Calendar | |
2681 * @method initStyles | |
2682 */ | |
2683 initStyles : function() { | |
2684 | |
2685 var defStyle = Calendar.STYLES; | |
2686 | |
2687 this.Style = { | |
2688 /** | |
2689 * @property Style.CSS_ROW_HEADER | |
2690 */ | |
2691 CSS_ROW_HEADER: defStyle.CSS_ROW_HEADER, | |
2692 /** | |
2693 * @property Style.CSS_ROW_FOOTER | |
2694 */ | |
2695 CSS_ROW_FOOTER: defStyle.CSS_ROW_FOOTER, | |
2696 /** | |
2697 * @property Style.CSS_CELL | |
2698 */ | |
2699 CSS_CELL : defStyle.CSS_CELL, | |
2700 /** | |
2701 * @property Style.CSS_CELL_SELECTOR | |
2702 */ | |
2703 CSS_CELL_SELECTOR : defStyle.CSS_CELL_SELECTOR, | |
2704 /** | |
2705 * @property Style.CSS_CELL_SELECTED | |
2706 */ | |
2707 CSS_CELL_SELECTED : defStyle.CSS_CELL_SELECTED, | |
2708 /** | |
2709 * @property Style.CSS_CELL_SELECTABLE | |
2710 */ | |
2711 CSS_CELL_SELECTABLE : defStyle.CSS_CELL_SELECTABLE, | |
2712 /** | |
2713 * @property Style.CSS_CELL_RESTRICTED | |
2714 */ | |
2715 CSS_CELL_RESTRICTED : defStyle.CSS_CELL_RESTRICTED, | |
2716 /** | |
2717 * @property Style.CSS_CELL_TODAY | |
2718 */ | |
2719 CSS_CELL_TODAY : defStyle.CSS_CELL_TODAY, | |
2720 /** | |
2721 * @property Style.CSS_CELL_OOM | |
2722 */ | |
2723 CSS_CELL_OOM : defStyle.CSS_CELL_OOM, | |
2724 /** | |
2725 * @property Style.CSS_CELL_OOB | |
2726 */ | |
2727 CSS_CELL_OOB : defStyle.CSS_CELL_OOB, | |
2728 /** | |
2729 * @property Style.CSS_HEADER | |
2730 */ | |
2731 CSS_HEADER : defStyle.CSS_HEADER, | |
2732 /** | |
2733 * @property Style.CSS_HEADER_TEXT | |
2734 */ | |
2735 CSS_HEADER_TEXT : defStyle.CSS_HEADER_TEXT, | |
2736 /** | |
2737 * @property Style.CSS_BODY | |
2738 */ | |
2739 CSS_BODY : defStyle.CSS_BODY, | |
2740 /** | |
2741 * @property Style.CSS_WEEKDAY_CELL | |
2742 */ | |
2743 CSS_WEEKDAY_CELL : defStyle.CSS_WEEKDAY_CELL, | |
2744 /** | |
2745 * @property Style.CSS_WEEKDAY_ROW | |
2746 */ | |
2747 CSS_WEEKDAY_ROW : defStyle.CSS_WEEKDAY_ROW, | |
2748 /** | |
2749 * @property Style.CSS_FOOTER | |
2750 */ | |
2751 CSS_FOOTER : defStyle.CSS_FOOTER, | |
2752 /** | |
2753 * @property Style.CSS_CALENDAR | |
2754 */ | |
2755 CSS_CALENDAR : defStyle.CSS_CALENDAR, | |
2756 /** | |
2757 * @property Style.CSS_SINGLE | |
2758 */ | |
2759 CSS_SINGLE : defStyle.CSS_SINGLE, | |
2760 /** | |
2761 * @property Style.CSS_CONTAINER | |
2762 */ | |
2763 CSS_CONTAINER : defStyle.CSS_CONTAINER, | |
2764 /** | |
2765 * @property Style.CSS_NAV_LEFT | |
2766 */ | |
2767 CSS_NAV_LEFT : defStyle.CSS_NAV_LEFT, | |
2768 /** | |
2769 * @property Style.CSS_NAV_RIGHT | |
2770 */ | |
2771 CSS_NAV_RIGHT : defStyle.CSS_NAV_RIGHT, | |
2772 /** | |
2773 * @property Style.CSS_NAV | |
2774 */ | |
2775 CSS_NAV : defStyle.CSS_NAV, | |
2776 /** | |
2777 * @property Style.CSS_CLOSE | |
2778 */ | |
2779 CSS_CLOSE : defStyle.CSS_CLOSE, | |
2780 /** | |
2781 * @property Style.CSS_CELL_TOP | |
2782 */ | |
2783 CSS_CELL_TOP : defStyle.CSS_CELL_TOP, | |
2784 /** | |
2785 * @property Style.CSS_CELL_LEFT | |
2786 */ | |
2787 CSS_CELL_LEFT : defStyle.CSS_CELL_LEFT, | |
2788 /** | |
2789 * @property Style.CSS_CELL_RIGHT | |
2790 */ | |
2791 CSS_CELL_RIGHT : defStyle.CSS_CELL_RIGHT, | |
2792 /** | |
2793 * @property Style.CSS_CELL_BOTTOM | |
2794 */ | |
2795 CSS_CELL_BOTTOM : defStyle.CSS_CELL_BOTTOM, | |
2796 /** | |
2797 * @property Style.CSS_CELL_HOVER | |
2798 */ | |
2799 CSS_CELL_HOVER : defStyle.CSS_CELL_HOVER, | |
2800 /** | |
2801 * @property Style.CSS_CELL_HIGHLIGHT1 | |
2802 */ | |
2803 CSS_CELL_HIGHLIGHT1 : defStyle.CSS_CELL_HIGHLIGHT1, | |
2804 /** | |
2805 * @property Style.CSS_CELL_HIGHLIGHT2 | |
2806 */ | |
2807 CSS_CELL_HIGHLIGHT2 : defStyle.CSS_CELL_HIGHLIGHT2, | |
2808 /** | |
2809 * @property Style.CSS_CELL_HIGHLIGHT3 | |
2810 */ | |
2811 CSS_CELL_HIGHLIGHT3 : defStyle.CSS_CELL_HIGHLIGHT3, | |
2812 /** | |
2813 * @property Style.CSS_CELL_HIGHLIGHT4 | |
2814 */ | |
2815 CSS_CELL_HIGHLIGHT4 : defStyle.CSS_CELL_HIGHLIGHT4, | |
2816 /** | |
2817 * @property Style.CSS_WITH_TITLE | |
2818 */ | |
2819 CSS_WITH_TITLE : defStyle.CSS_WITH_TITLE, | |
2820 /** | |
2821 * @property Style.CSS_FIXED_SIZE | |
2822 */ | |
2823 CSS_FIXED_SIZE : defStyle.CSS_FIXED_SIZE, | |
2824 /** | |
2825 * @property Style.CSS_LINK_CLOSE | |
2826 */ | |
2827 CSS_LINK_CLOSE : defStyle.CSS_LINK_CLOSE | |
2828 }; | |
2829 }, | |
2830 | |
2831 /** | |
2832 * Builds the date label that will be displayed in the calendar header or | |
2833 * footer, depending on configuration. | |
2834 * @method buildMonthLabel | |
2835 * @return {String} The formatted calendar month label | |
2836 */ | |
2837 buildMonthLabel : function() { | |
2838 return this._buildMonthLabel(this.cfg.getProperty(DEF_CFG.PAGEDATE.key)); | |
2839 }, | |
2840 | |
2841 /** | |
2842 * Helper method, to format a Month Year string, given a JavaScript Date, based on the | |
2843 * Calendar localization settings | |
2844 * | |
2845 * @method _buildMonthLabel | |
2846 * @private | |
2847 * @param {Date} date | |
2848 * @return {String} Formated month, year string | |
2849 */ | |
2850 _buildMonthLabel : function(date) { | |
2851 var monthLabel = this.Locale.LOCALE_MONTHS[date.getMonth()] + this.Locale.MY_LABEL_MONTH_SUFFIX, | |
2852 yearLabel = (date.getFullYear() + this.Locale.YEAR_OFFSET) + this.Locale.MY_LABEL_YEAR_SUFFIX; | |
2853 | |
2854 if (this.Locale.MY_LABEL_MONTH_POSITION == 2 || this.Locale.MY_LABEL_YEAR_POSITION == 1) { | |
2855 return yearLabel + monthLabel; | |
2856 } else { | |
2857 return monthLabel + yearLabel; | |
2858 } | |
2859 }, | |
2860 | |
2861 /** | |
2862 * Builds the date digit that will be displayed in calendar cells | |
2863 * @method buildDayLabel | |
2864 * @param {Date} workingDate The current working date | |
2865 * @return {String} The formatted day label | |
2866 */ | |
2867 buildDayLabel : function(workingDate) { | |
2868 return workingDate.getDate(); | |
2869 }, | |
2870 | |
2871 /** | |
2872 * Creates the title bar element and adds it to Calendar container DIV | |
2873 * | |
2874 * @method createTitleBar | |
2875 * @param {String} strTitle The title to display in the title bar | |
2876 * @return The title bar element | |
2877 */ | |
2878 createTitleBar : function(strTitle) { | |
2879 var tDiv = Dom.getElementsByClassName(YAHOO.widget.CalendarGroup.CSS_2UPTITLE, "div", this.oDomContainer)[0] || document.createElement("div"); | |
2880 tDiv.className = YAHOO.widget.CalendarGroup.CSS_2UPTITLE; | |
2881 tDiv.innerHTML = strTitle; | |
2882 this.oDomContainer.insertBefore(tDiv, this.oDomContainer.firstChild); | |
2883 | |
2884 Dom.addClass(this.oDomContainer, this.Style.CSS_WITH_TITLE); | |
2885 | |
2886 return tDiv; | |
2887 }, | |
2888 | |
2889 /** | |
2890 * Removes the title bar element from the DOM | |
2891 * | |
2892 * @method removeTitleBar | |
2893 */ | |
2894 removeTitleBar : function() { | |
2895 var tDiv = Dom.getElementsByClassName(YAHOO.widget.CalendarGroup.CSS_2UPTITLE, "div", this.oDomContainer)[0] || null; | |
2896 if (tDiv) { | |
2897 Event.purgeElement(tDiv); | |
2898 this.oDomContainer.removeChild(tDiv); | |
2899 } | |
2900 Dom.removeClass(this.oDomContainer, this.Style.CSS_WITH_TITLE); | |
2901 }, | |
2902 | |
2903 /** | |
2904 * Creates the close button HTML element and adds it to Calendar container DIV | |
2905 * | |
2906 * @method createCloseButton | |
2907 * @return The close HTML element created | |
2908 */ | |
2909 createCloseButton : function() { | |
2910 var cssClose = YAHOO.widget.CalendarGroup.CSS_2UPCLOSE, | |
2911 cssLinkClose = this.Style.CSS_LINK_CLOSE, | |
2912 DEPR_CLOSE_PATH = "us/my/bn/x_d.gif", | |
2913 | |
2914 lnk = Dom.getElementsByClassName(cssLinkClose, "a", this.oDomContainer)[0], | |
2915 strings = this.cfg.getProperty(DEF_CFG.STRINGS.key), | |
2916 closeStr = (strings && strings.close) ? strings.close : ""; | |
2917 | |
2918 if (!lnk) { | |
2919 lnk = document.createElement("a"); | |
2920 Event.addListener(lnk, "click", function(e, cal) { | |
2921 cal.hide(); | |
2922 Event.preventDefault(e); | |
2923 }, this); | |
2924 } | |
2925 | |
2926 lnk.href = "#"; | |
2927 lnk.className = cssLinkClose; | |
2928 | |
2929 if (Calendar.IMG_ROOT !== null) { | |
2930 var img = Dom.getElementsByClassName(cssClose, "img", lnk)[0] || document.createElement("img"); | |
2931 img.src = Calendar.IMG_ROOT + DEPR_CLOSE_PATH; | |
2932 img.className = cssClose; | |
2933 lnk.appendChild(img); | |
2934 } else { | |
2935 lnk.innerHTML = '<span class="' + cssClose + ' ' + this.Style.CSS_CLOSE + '">' + closeStr + '</span>'; | |
2936 } | |
2937 this.oDomContainer.appendChild(lnk); | |
2938 | |
2939 return lnk; | |
2940 }, | |
2941 | |
2942 /** | |
2943 * Removes the close button HTML element from the DOM | |
2944 * | |
2945 * @method removeCloseButton | |
2946 */ | |
2947 removeCloseButton : function() { | |
2948 var btn = Dom.getElementsByClassName(this.Style.CSS_LINK_CLOSE, "a", this.oDomContainer)[0] || null; | |
2949 if (btn) { | |
2950 Event.purgeElement(btn); | |
2951 this.oDomContainer.removeChild(btn); | |
2952 } | |
2953 }, | |
2954 | |
2955 /** | |
2956 * Renders the calendar header. | |
2957 * @method renderHeader | |
2958 * @param {Array} html The current working HTML array | |
2959 * @return {Array} The current working HTML array | |
2960 */ | |
2961 renderHeader : function(html) { | |
2962 | |
2963 this.logger.log("Rendering header", "render"); | |
2964 | |
2965 var colSpan = 7, | |
2966 DEPR_NAV_LEFT = "us/tr/callt.gif", | |
2967 DEPR_NAV_RIGHT = "us/tr/calrt.gif", | |
2968 cfg = this.cfg, | |
2969 pageDate = cfg.getProperty(DEF_CFG.PAGEDATE.key), | |
2970 strings= cfg.getProperty(DEF_CFG.STRINGS.key), | |
2971 prevStr = (strings && strings.previousMonth) ? strings.previousMonth : "", | |
2972 nextStr = (strings && strings.nextMonth) ? strings.nextMonth : "", | |
2973 monthLabel; | |
2974 | |
2975 if (cfg.getProperty(DEF_CFG.SHOW_WEEK_HEADER.key)) { | |
2976 colSpan += 1; | |
2977 } | |
2978 | |
2979 if (cfg.getProperty(DEF_CFG.SHOW_WEEK_FOOTER.key)) { | |
2980 colSpan += 1; | |
2981 } | |
2982 | |
2983 html[html.length] = "<thead>"; | |
2984 html[html.length] = "<tr>"; | |
2985 html[html.length] = '<th colspan="' + colSpan + '" class="' + this.Style.CSS_HEADER_TEXT + '">'; | |
2986 html[html.length] = '<div class="' + this.Style.CSS_HEADER + '">'; | |
2987 | |
2988 var renderLeft, renderRight = false; | |
2989 | |
2990 if (this.parent) { | |
2991 if (this.index === 0) { | |
2992 renderLeft = true; | |
2993 } | |
2994 if (this.index == (this.parent.cfg.getProperty("pages") -1)) { | |
2995 renderRight = true; | |
2996 } | |
2997 } else { | |
2998 renderLeft = true; | |
2999 renderRight = true; | |
3000 } | |
3001 | |
3002 if (renderLeft) { | |
3003 monthLabel = this._buildMonthLabel(DateMath.subtract(pageDate, DateMath.MONTH, 1)); | |
3004 | |
3005 var leftArrow = cfg.getProperty(DEF_CFG.NAV_ARROW_LEFT.key); | |
3006 // 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 | |
3007 if (leftArrow === null && Calendar.IMG_ROOT !== null) { | |
3008 leftArrow = Calendar.IMG_ROOT + DEPR_NAV_LEFT; | |
3009 } | |
3010 var leftStyle = (leftArrow === null) ? "" : ' style="background-image:url(' + leftArrow + ')"'; | |
3011 html[html.length] = '<a class="' + this.Style.CSS_NAV_LEFT + '"' + leftStyle + ' href="#">' + prevStr + ' (' + monthLabel + ')' + '</a>'; | |
3012 } | |
3013 | |
3014 var lbl = this.buildMonthLabel(); | |
3015 var cal = this.parent || this; | |
3016 if (cal.cfg.getProperty("navigator")) { | |
3017 lbl = "<a class=\"" + this.Style.CSS_NAV + "\" href=\"#\">" + lbl + "</a>"; | |
3018 } | |
3019 html[html.length] = lbl; | |
3020 | |
3021 if (renderRight) { | |
3022 monthLabel = this._buildMonthLabel(DateMath.add(pageDate, DateMath.MONTH, 1)); | |
3023 | |
3024 var rightArrow = cfg.getProperty(DEF_CFG.NAV_ARROW_RIGHT.key); | |
3025 if (rightArrow === null && Calendar.IMG_ROOT !== null) { | |
3026 rightArrow = Calendar.IMG_ROOT + DEPR_NAV_RIGHT; | |
3027 } | |
3028 var rightStyle = (rightArrow === null) ? "" : ' style="background-image:url(' + rightArrow + ')"'; | |
3029 html[html.length] = '<a class="' + this.Style.CSS_NAV_RIGHT + '"' + rightStyle + ' href="#">' + nextStr + ' (' + monthLabel + ')' + '</a>'; | |
3030 } | |
3031 | |
3032 html[html.length] = '</div>\n</th>\n</tr>'; | |
3033 | |
3034 if (cfg.getProperty(DEF_CFG.SHOW_WEEKDAYS.key)) { | |
3035 html = this.buildWeekdays(html); | |
3036 } | |
3037 | |
3038 html[html.length] = '</thead>'; | |
3039 | |
3040 return html; | |
3041 }, | |
3042 | |
3043 /** | |
3044 * Renders the Calendar's weekday headers. | |
3045 * @method buildWeekdays | |
3046 * @param {Array} html The current working HTML array | |
3047 * @return {Array} The current working HTML array | |
3048 */ | |
3049 buildWeekdays : function(html) { | |
3050 | |
3051 html[html.length] = '<tr class="' + this.Style.CSS_WEEKDAY_ROW + '">'; | |
3052 | |
3053 if (this.cfg.getProperty(DEF_CFG.SHOW_WEEK_HEADER.key)) { | |
3054 html[html.length] = '<th> </th>'; | |
3055 } | |
3056 | |
3057 for(var i=0;i < this.Locale.LOCALE_WEEKDAYS.length; ++i) { | |
3058 html[html.length] = '<th class="' + this.Style.CSS_WEEKDAY_CELL + '">' + this.Locale.LOCALE_WEEKDAYS[i] + '</th>'; | |
3059 } | |
3060 | |
3061 if (this.cfg.getProperty(DEF_CFG.SHOW_WEEK_FOOTER.key)) { | |
3062 html[html.length] = '<th> </th>'; | |
3063 } | |
3064 | |
3065 html[html.length] = '</tr>'; | |
3066 | |
3067 return html; | |
3068 }, | |
3069 | |
3070 /** | |
3071 * Renders the calendar body. | |
3072 * @method renderBody | |
3073 * @param {Date} workingDate The current working Date being used for the render process | |
3074 * @param {Array} html The current working HTML array | |
3075 * @return {Array} The current working HTML array | |
3076 */ | |
3077 renderBody : function(workingDate, html) { | |
3078 this.logger.log("Rendering body", "render"); | |
3079 | |
3080 var startDay = this.cfg.getProperty(DEF_CFG.START_WEEKDAY.key); | |
3081 | |
3082 this.preMonthDays = workingDate.getDay(); | |
3083 if (startDay > 0) { | |
3084 this.preMonthDays -= startDay; | |
3085 } | |
3086 if (this.preMonthDays < 0) { | |
3087 this.preMonthDays += 7; | |
3088 } | |
3089 | |
3090 this.monthDays = DateMath.findMonthEnd(workingDate).getDate(); | |
3091 this.postMonthDays = Calendar.DISPLAY_DAYS-this.preMonthDays-this.monthDays; | |
3092 | |
3093 this.logger.log(this.preMonthDays + " preciding out-of-month days", "render"); | |
3094 this.logger.log(this.monthDays + " month days", "render"); | |
3095 this.logger.log(this.postMonthDays + " post-month days", "render"); | |
3096 | |
3097 workingDate = DateMath.subtract(workingDate, DateMath.DAY, this.preMonthDays); | |
3098 this.logger.log("Calendar page starts on " + workingDate, "render"); | |
3099 | |
3100 var weekNum, | |
3101 weekClass, | |
3102 weekPrefix = "w", | |
3103 cellPrefix = "_cell", | |
3104 workingDayPrefix = "wd", | |
3105 dayPrefix = "d", | |
3106 cellRenderers, | |
3107 renderer, | |
3108 t = this.today, | |
3109 cfg = this.cfg, | |
3110 todayYear = t.getFullYear(), | |
3111 todayMonth = t.getMonth(), | |
3112 todayDate = t.getDate(), | |
3113 useDate = cfg.getProperty(DEF_CFG.PAGEDATE.key), | |
3114 hideBlankWeeks = cfg.getProperty(DEF_CFG.HIDE_BLANK_WEEKS.key), | |
3115 showWeekFooter = cfg.getProperty(DEF_CFG.SHOW_WEEK_FOOTER.key), | |
3116 showWeekHeader = cfg.getProperty(DEF_CFG.SHOW_WEEK_HEADER.key), | |
3117 mindate = cfg.getProperty(DEF_CFG.MINDATE.key), | |
3118 maxdate = cfg.getProperty(DEF_CFG.MAXDATE.key), | |
3119 yearOffset = this.Locale.YEAR_OFFSET; | |
3120 | |
3121 if (mindate) { | |
3122 mindate = DateMath.clearTime(mindate); | |
3123 } | |
3124 if (maxdate) { | |
3125 maxdate = DateMath.clearTime(maxdate); | |
3126 } | |
3127 | |
3128 html[html.length] = '<tbody class="m' + (useDate.getMonth()+1) + ' ' + this.Style.CSS_BODY + '">'; | |
3129 | |
3130 var i = 0, | |
3131 tempDiv = document.createElement("div"), | |
3132 cell = document.createElement("td"); | |
3133 | |
3134 tempDiv.appendChild(cell); | |
3135 | |
3136 var cal = this.parent || this; | |
3137 | |
3138 for (var r=0;r<6;r++) { | |
3139 weekNum = DateMath.getWeekNumber(workingDate, startDay); | |
3140 weekClass = weekPrefix + weekNum; | |
3141 | |
3142 // Local OOM check for performance, since we already have pagedate | |
3143 if (r !== 0 && hideBlankWeeks === true && workingDate.getMonth() != useDate.getMonth()) { | |
3144 break; | |
3145 } else { | |
3146 html[html.length] = '<tr class="' + weekClass + '">'; | |
3147 | |
3148 if (showWeekHeader) { html = this.renderRowHeader(weekNum, html); } | |
3149 | |
3150 for (var d=0; d < 7; d++){ // Render actual days | |
3151 | |
3152 cellRenderers = []; | |
3153 | |
3154 this.clearElement(cell); | |
3155 cell.className = this.Style.CSS_CELL; | |
3156 cell.id = this.id + cellPrefix + i; | |
3157 this.logger.log("Rendering cell " + cell.id + " (" + workingDate.getFullYear() + yearOffset + "-" + (workingDate.getMonth()+1) + "-" + workingDate.getDate() + ")", "cellrender"); | |
3158 | |
3159 if (workingDate.getDate() == todayDate && | |
3160 workingDate.getMonth() == todayMonth && | |
3161 workingDate.getFullYear() == todayYear) { | |
3162 cellRenderers[cellRenderers.length]=cal.renderCellStyleToday; | |
3163 } | |
3164 | |
3165 var workingArray = [workingDate.getFullYear(),workingDate.getMonth()+1,workingDate.getDate()]; | |
3166 this.cellDates[this.cellDates.length] = workingArray; // Add this date to cellDates | |
3167 | |
3168 // Local OOM check for performance, since we already have pagedate | |
3169 if (workingDate.getMonth() != useDate.getMonth()) { | |
3170 cellRenderers[cellRenderers.length]=cal.renderCellNotThisMonth; | |
3171 } else { | |
3172 Dom.addClass(cell, workingDayPrefix + workingDate.getDay()); | |
3173 Dom.addClass(cell, dayPrefix + workingDate.getDate()); | |
3174 | |
3175 for (var s=0;s<this.renderStack.length;++s) { | |
3176 | |
3177 renderer = null; | |
3178 | |
3179 var rArray = this.renderStack[s], | |
3180 type = rArray[0], | |
3181 month, | |
3182 day, | |
3183 year; | |
3184 | |
3185 switch (type) { | |
3186 case Calendar.DATE: | |
3187 month = rArray[1][1]; | |
3188 day = rArray[1][2]; | |
3189 year = rArray[1][0]; | |
3190 | |
3191 if (workingDate.getMonth()+1 == month && workingDate.getDate() == day && workingDate.getFullYear() == year) { | |
3192 renderer = rArray[2]; | |
3193 this.renderStack.splice(s,1); | |
3194 } | |
3195 break; | |
3196 case Calendar.MONTH_DAY: | |
3197 month = rArray[1][0]; | |
3198 day = rArray[1][1]; | |
3199 | |
3200 if (workingDate.getMonth()+1 == month && workingDate.getDate() == day) { | |
3201 renderer = rArray[2]; | |
3202 this.renderStack.splice(s,1); | |
3203 } | |
3204 break; | |
3205 case Calendar.RANGE: | |
3206 var date1 = rArray[1][0], | |
3207 date2 = rArray[1][1], | |
3208 d1month = date1[1], | |
3209 d1day = date1[2], | |
3210 d1year = date1[0], | |
3211 d1 = DateMath.getDate(d1year, d1month-1, d1day), | |
3212 d2month = date2[1], | |
3213 d2day = date2[2], | |
3214 d2year = date2[0], | |
3215 d2 = DateMath.getDate(d2year, d2month-1, d2day); | |
3216 | |
3217 if (workingDate.getTime() >= d1.getTime() && workingDate.getTime() <= d2.getTime()) { | |
3218 renderer = rArray[2]; | |
3219 | |
3220 if (workingDate.getTime()==d2.getTime()) { | |
3221 this.renderStack.splice(s,1); | |
3222 } | |
3223 } | |
3224 break; | |
3225 case Calendar.WEEKDAY: | |
3226 var weekday = rArray[1][0]; | |
3227 if (workingDate.getDay()+1 == weekday) { | |
3228 renderer = rArray[2]; | |
3229 } | |
3230 break; | |
3231 case Calendar.MONTH: | |
3232 month = rArray[1][0]; | |
3233 if (workingDate.getMonth()+1 == month) { | |
3234 renderer = rArray[2]; | |
3235 } | |
3236 break; | |
3237 } | |
3238 | |
3239 if (renderer) { | |
3240 cellRenderers[cellRenderers.length]=renderer; | |
3241 } | |
3242 } | |
3243 | |
3244 } | |
3245 | |
3246 if (this._indexOfSelectedFieldArray(workingArray) > -1) { | |
3247 cellRenderers[cellRenderers.length]=cal.renderCellStyleSelected; | |
3248 } | |
3249 | |
3250 if ((mindate && (workingDate.getTime() < mindate.getTime())) || | |
3251 (maxdate && (workingDate.getTime() > maxdate.getTime())) | |
3252 ) { | |
3253 cellRenderers[cellRenderers.length]=cal.renderOutOfBoundsDate; | |
3254 } else { | |
3255 cellRenderers[cellRenderers.length]=cal.styleCellDefault; | |
3256 cellRenderers[cellRenderers.length]=cal.renderCellDefault; | |
3257 } | |
3258 | |
3259 for (var x=0; x < cellRenderers.length; ++x) { | |
3260 this.logger.log("renderer[" + x + "] for (" + workingDate.getFullYear() + yearOffset + "-" + (workingDate.getMonth()+1) + "-" + workingDate.getDate() + ")", "cellrender"); | |
3261 if (cellRenderers[x].call(cal, workingDate, cell) == Calendar.STOP_RENDER) { | |
3262 break; | |
3263 } | |
3264 } | |
3265 | |
3266 workingDate.setTime(workingDate.getTime() + DateMath.ONE_DAY_MS); | |
3267 // Just in case we crossed DST/Summertime boundaries | |
3268 workingDate = DateMath.clearTime(workingDate); | |
3269 | |
3270 if (i >= 0 && i <= 6) { | |
3271 Dom.addClass(cell, this.Style.CSS_CELL_TOP); | |
3272 } | |
3273 if ((i % 7) === 0) { | |
3274 Dom.addClass(cell, this.Style.CSS_CELL_LEFT); | |
3275 } | |
3276 if (((i+1) % 7) === 0) { | |
3277 Dom.addClass(cell, this.Style.CSS_CELL_RIGHT); | |
3278 } | |
3279 | |
3280 var postDays = this.postMonthDays; | |
3281 if (hideBlankWeeks && postDays >= 7) { | |
3282 var blankWeeks = Math.floor(postDays/7); | |
3283 for (var p=0;p<blankWeeks;++p) { | |
3284 postDays -= 7; | |
3285 } | |
3286 } | |
3287 | |
3288 if (i >= ((this.preMonthDays+postDays+this.monthDays)-7)) { | |
3289 Dom.addClass(cell, this.Style.CSS_CELL_BOTTOM); | |
3290 } | |
3291 | |
3292 html[html.length] = tempDiv.innerHTML; | |
3293 i++; | |
3294 } | |
3295 | |
3296 if (showWeekFooter) { html = this.renderRowFooter(weekNum, html); } | |
3297 | |
3298 html[html.length] = '</tr>'; | |
3299 } | |
3300 } | |
3301 | |
3302 html[html.length] = '</tbody>'; | |
3303 | |
3304 return html; | |
3305 }, | |
3306 | |
3307 /** | |
3308 * Renders the calendar footer. In the default implementation, there is | |
3309 * no footer. | |
3310 * @method renderFooter | |
3311 * @param {Array} html The current working HTML array | |
3312 * @return {Array} The current working HTML array | |
3313 */ | |
3314 renderFooter : function(html) { return html; }, | |
3315 | |
3316 /** | |
3317 * Renders the calendar after it has been configured. The render() method has a specific call chain that will execute | |
3318 * when the method is called: renderHeader, renderBody, renderFooter. | |
3319 * Refer to the documentation for those methods for information on | |
3320 * individual render tasks. | |
3321 * @method render | |
3322 */ | |
3323 render : function() { | |
3324 this.beforeRenderEvent.fire(); | |
3325 | |
3326 // Find starting day of the current month | |
3327 var workingDate = DateMath.findMonthStart(this.cfg.getProperty(DEF_CFG.PAGEDATE.key)); | |
3328 | |
3329 this.resetRenderers(); | |
3330 this.cellDates.length = 0; | |
3331 | |
3332 Event.purgeElement(this.oDomContainer, true); | |
3333 | |
3334 var html = []; | |
3335 | |
3336 html[html.length] = '<table cellSpacing="0" class="' + this.Style.CSS_CALENDAR + ' y' + (workingDate.getFullYear() + this.Locale.YEAR_OFFSET) +'" id="' + this.id + '">'; | |
3337 html = this.renderHeader(html); | |
3338 html = this.renderBody(workingDate, html); | |
3339 html = this.renderFooter(html); | |
3340 html[html.length] = '</table>'; | |
3341 | |
3342 this.oDomContainer.innerHTML = html.join("\n"); | |
3343 | |
3344 this.applyListeners(); | |
3345 this.cells = Dom.getElementsByClassName(this.Style.CSS_CELL, "td", this.id); | |
3346 | |
3347 this.cfg.refireEvent(DEF_CFG.TITLE.key); | |
3348 this.cfg.refireEvent(DEF_CFG.CLOSE.key); | |
3349 this.cfg.refireEvent(DEF_CFG.IFRAME.key); | |
3350 | |
3351 this.renderEvent.fire(); | |
3352 }, | |
3353 | |
3354 /** | |
3355 * Applies the Calendar's DOM listeners to applicable elements. | |
3356 * @method applyListeners | |
3357 */ | |
3358 applyListeners : function() { | |
3359 var root = this.oDomContainer, | |
3360 cal = this.parent || this, | |
3361 anchor = "a", | |
3362 click = "click"; | |
3363 | |
3364 var linkLeft = Dom.getElementsByClassName(this.Style.CSS_NAV_LEFT, anchor, root), | |
3365 linkRight = Dom.getElementsByClassName(this.Style.CSS_NAV_RIGHT, anchor, root); | |
3366 | |
3367 if (linkLeft && linkLeft.length > 0) { | |
3368 this.linkLeft = linkLeft[0]; | |
3369 Event.addListener(this.linkLeft, click, this.doPreviousMonthNav, cal, true); | |
3370 } | |
3371 | |
3372 if (linkRight && linkRight.length > 0) { | |
3373 this.linkRight = linkRight[0]; | |
3374 Event.addListener(this.linkRight, click, this.doNextMonthNav, cal, true); | |
3375 } | |
3376 | |
3377 if (cal.cfg.getProperty("navigator") !== null) { | |
3378 this.applyNavListeners(); | |
3379 } | |
3380 | |
3381 if (this.domEventMap) { | |
3382 var el,elements; | |
3383 for (var cls in this.domEventMap) { | |
3384 if (Lang.hasOwnProperty(this.domEventMap, cls)) { | |
3385 var items = this.domEventMap[cls]; | |
3386 | |
3387 if (! (items instanceof Array)) { | |
3388 items = [items]; | |
3389 } | |
3390 | |
3391 for (var i=0;i<items.length;i++) { | |
3392 var item = items[i]; | |
3393 elements = Dom.getElementsByClassName(cls, item.tag, this.oDomContainer); | |
3394 | |
3395 for (var c=0;c<elements.length;c++) { | |
3396 el = elements[c]; | |
3397 Event.addListener(el, item.event, item.handler, item.scope, item.correct ); | |
3398 } | |
3399 } | |
3400 } | |
3401 } | |
3402 } | |
3403 | |
3404 Event.addListener(this.oDomContainer, "click", this.doSelectCell, this); | |
3405 Event.addListener(this.oDomContainer, "mouseover", this.doCellMouseOver, this); | |
3406 Event.addListener(this.oDomContainer, "mouseout", this.doCellMouseOut, this); | |
3407 }, | |
3408 | |
3409 applyNavListeners : function() { | |
3410 var calParent = this.parent || this, | |
3411 cal = this, | |
3412 navBtns = Dom.getElementsByClassName(this.Style.CSS_NAV, "a", this.oDomContainer); | |
3413 | |
3414 if (navBtns.length > 0) { | |
3415 | |
3416 Event.addListener(navBtns, "click", function (e, obj) { | |
3417 var target = Event.getTarget(e); | |
3418 // this == navBtn | |
3419 if (this === target || Dom.isAncestor(this, target)) { | |
3420 Event.preventDefault(e); | |
3421 } | |
3422 var navigator = calParent.oNavigator; | |
3423 if (navigator) { | |
3424 var pgdate = cal.cfg.getProperty("pagedate"); | |
3425 navigator.setYear(pgdate.getFullYear() + cal.Locale.YEAR_OFFSET); | |
3426 navigator.setMonth(pgdate.getMonth()); | |
3427 navigator.show(); | |
3428 } | |
3429 }); | |
3430 } | |
3431 }, | |
3432 | |
3433 /** | |
3434 * Retrieves the Date object for the specified Calendar cell | |
3435 * @method getDateByCellId | |
3436 * @param {String} id The id of the cell | |
3437 * @return {Date} The Date object for the specified Calendar cell | |
3438 */ | |
3439 getDateByCellId : function(id) { | |
3440 var date = this.getDateFieldsByCellId(id); | |
3441 return (date) ? DateMath.getDate(date[0],date[1]-1,date[2]) : null; | |
3442 }, | |
3443 | |
3444 /** | |
3445 * Retrieves the Date object for the specified Calendar cell | |
3446 * @method getDateFieldsByCellId | |
3447 * @param {String} id The id of the cell | |
3448 * @return {Array} The array of Date fields for the specified Calendar cell | |
3449 */ | |
3450 getDateFieldsByCellId : function(id) { | |
3451 id = this.getIndexFromId(id); | |
3452 return (id > -1) ? this.cellDates[id] : null; | |
3453 }, | |
3454 | |
3455 /** | |
3456 * Find the Calendar's cell index for a given date. | |
3457 * If the date is not found, the method returns -1. | |
3458 * <p> | |
3459 * The returned index can be used to lookup the cell HTMLElement | |
3460 * using the Calendar's cells array or passed to selectCell to select | |
3461 * cells by index. | |
3462 * </p> | |
3463 * | |
3464 * See <a href="#cells">cells</a>, <a href="#selectCell">selectCell</a>. | |
3465 * | |
3466 * @method getCellIndex | |
3467 * @param {Date} date JavaScript Date object, for which to find a cell index. | |
3468 * @return {Number} The index of the date in Calendars cellDates/cells arrays, or -1 if the date | |
3469 * is not on the curently rendered Calendar page. | |
3470 */ | |
3471 getCellIndex : function(date) { | |
3472 var idx = -1; | |
3473 if (date) { | |
3474 var m = date.getMonth(), | |
3475 y = date.getFullYear(), | |
3476 d = date.getDate(), | |
3477 dates = this.cellDates; | |
3478 | |
3479 for (var i = 0; i < dates.length; ++i) { | |
3480 var cellDate = dates[i]; | |
3481 if (cellDate[0] === y && cellDate[1] === m+1 && cellDate[2] === d) { | |
3482 idx = i; | |
3483 break; | |
3484 } | |
3485 } | |
3486 } | |
3487 return idx; | |
3488 }, | |
3489 | |
3490 /** | |
3491 * Given the id used to mark each Calendar cell, this method | |
3492 * extracts the index number from the id. | |
3493 * | |
3494 * @param {String} strId The cell id | |
3495 * @return {Number} The index of the cell, or -1 if id does not contain an index number | |
3496 */ | |
3497 getIndexFromId : function(strId) { | |
3498 var idx = -1, | |
3499 li = strId.lastIndexOf("_cell"); | |
3500 | |
3501 if (li > -1) { | |
3502 idx = parseInt(strId.substring(li + 5), 10); | |
3503 } | |
3504 | |
3505 return idx; | |
3506 }, | |
3507 | |
3508 // BEGIN BUILT-IN TABLE CELL RENDERERS | |
3509 | |
3510 /** | |
3511 * Renders a cell that falls before the minimum date or after the maximum date. | |
3512 * widget class. | |
3513 * @method renderOutOfBoundsDate | |
3514 * @param {Date} workingDate The current working Date object being used to generate the calendar | |
3515 * @param {HTMLTableCellElement} cell The current working cell in the calendar | |
3516 * @return {String} YAHOO.widget.Calendar.STOP_RENDER if rendering should stop with this style, null or nothing if rendering | |
3517 * should not be terminated | |
3518 */ | |
3519 renderOutOfBoundsDate : function(workingDate, cell) { | |
3520 Dom.addClass(cell, this.Style.CSS_CELL_OOB); | |
3521 cell.innerHTML = workingDate.getDate(); | |
3522 return Calendar.STOP_RENDER; | |
3523 }, | |
3524 | |
3525 /** | |
3526 * Renders the row header for a week. | |
3527 * @method renderRowHeader | |
3528 * @param {Number} weekNum The week number of the current row | |
3529 * @param {Array} cell The current working HTML array | |
3530 */ | |
3531 renderRowHeader : function(weekNum, html) { | |
3532 html[html.length] = '<th class="' + this.Style.CSS_ROW_HEADER + '">' + weekNum + '</th>'; | |
3533 return html; | |
3534 }, | |
3535 | |
3536 /** | |
3537 * Renders the row footer for a week. | |
3538 * @method renderRowFooter | |
3539 * @param {Number} weekNum The week number of the current row | |
3540 * @param {Array} cell The current working HTML array | |
3541 */ | |
3542 renderRowFooter : function(weekNum, html) { | |
3543 html[html.length] = '<th class="' + this.Style.CSS_ROW_FOOTER + '">' + weekNum + '</th>'; | |
3544 return html; | |
3545 }, | |
3546 | |
3547 /** | |
3548 * Renders a single standard calendar cell in the calendar widget table. | |
3549 * All logic for determining how a standard default cell will be rendered is | |
3550 * encapsulated in this method, and must be accounted for when extending the | |
3551 * widget class. | |
3552 * @method renderCellDefault | |
3553 * @param {Date} workingDate The current working Date object being used to generate the calendar | |
3554 * @param {HTMLTableCellElement} cell The current working cell in the calendar | |
3555 */ | |
3556 renderCellDefault : function(workingDate, cell) { | |
3557 cell.innerHTML = '<a href="#" class="' + this.Style.CSS_CELL_SELECTOR + '">' + this.buildDayLabel(workingDate) + "</a>"; | |
3558 }, | |
3559 | |
3560 /** | |
3561 * Styles a selectable cell. | |
3562 * @method styleCellDefault | |
3563 * @param {Date} workingDate The current working Date object being used to generate the calendar | |
3564 * @param {HTMLTableCellElement} cell The current working cell in the calendar | |
3565 */ | |
3566 styleCellDefault : function(workingDate, cell) { | |
3567 Dom.addClass(cell, this.Style.CSS_CELL_SELECTABLE); | |
3568 }, | |
3569 | |
3570 | |
3571 /** | |
3572 * Renders a single standard calendar cell using the CSS hightlight1 style | |
3573 * @method renderCellStyleHighlight1 | |
3574 * @param {Date} workingDate The current working Date object being used to generate the calendar | |
3575 * @param {HTMLTableCellElement} cell The current working cell in the calendar | |
3576 */ | |
3577 renderCellStyleHighlight1 : function(workingDate, cell) { | |
3578 Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT1); | |
3579 }, | |
3580 | |
3581 /** | |
3582 * Renders a single standard calendar cell using the CSS hightlight2 style | |
3583 * @method renderCellStyleHighlight2 | |
3584 * @param {Date} workingDate The current working Date object being used to generate the calendar | |
3585 * @param {HTMLTableCellElement} cell The current working cell in the calendar | |
3586 */ | |
3587 renderCellStyleHighlight2 : function(workingDate, cell) { | |
3588 Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT2); | |
3589 }, | |
3590 | |
3591 /** | |
3592 * Renders a single standard calendar cell using the CSS hightlight3 style | |
3593 * @method renderCellStyleHighlight3 | |
3594 * @param {Date} workingDate The current working Date object being used to generate the calendar | |
3595 * @param {HTMLTableCellElement} cell The current working cell in the calendar | |
3596 */ | |
3597 renderCellStyleHighlight3 : function(workingDate, cell) { | |
3598 Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT3); | |
3599 }, | |
3600 | |
3601 /** | |
3602 * Renders a single standard calendar cell using the CSS hightlight4 style | |
3603 * @method renderCellStyleHighlight4 | |
3604 * @param {Date} workingDate The current working Date object being used to generate the calendar | |
3605 * @param {HTMLTableCellElement} cell The current working cell in the calendar | |
3606 */ | |
3607 renderCellStyleHighlight4 : function(workingDate, cell) { | |
3608 Dom.addClass(cell, this.Style.CSS_CELL_HIGHLIGHT4); | |
3609 }, | |
3610 | |
3611 /** | |
3612 * Applies the default style used for rendering today's date to the current calendar cell | |
3613 * @method renderCellStyleToday | |
3614 * @param {Date} workingDate The current working Date object being used to generate the calendar | |
3615 * @param {HTMLTableCellElement} cell The current working cell in the calendar | |
3616 */ | |
3617 renderCellStyleToday : function(workingDate, cell) { | |
3618 Dom.addClass(cell, this.Style.CSS_CELL_TODAY); | |
3619 }, | |
3620 | |
3621 /** | |
3622 * Applies the default style used for rendering selected dates to the current calendar cell | |
3623 * @method renderCellStyleSelected | |
3624 * @param {Date} workingDate The current working Date object being used to generate the calendar | |
3625 * @param {HTMLTableCellElement} cell The current working cell in the calendar | |
3626 * @return {String} YAHOO.widget.Calendar.STOP_RENDER if rendering should stop with this style, null or nothing if rendering | |
3627 * should not be terminated | |
3628 */ | |
3629 renderCellStyleSelected : function(workingDate, cell) { | |
3630 Dom.addClass(cell, this.Style.CSS_CELL_SELECTED); | |
3631 }, | |
3632 | |
3633 /** | |
3634 * Applies the default style used for rendering dates that are not a part of the current | |
3635 * month (preceding or trailing the cells for the current month) | |
3636 * @method renderCellNotThisMonth | |
3637 * @param {Date} workingDate The current working Date object being used to generate the calendar | |
3638 * @param {HTMLTableCellElement} cell The current working cell in the calendar | |
3639 * @return {String} YAHOO.widget.Calendar.STOP_RENDER if rendering should stop with this style, null or nothing if rendering | |
3640 * should not be terminated | |
3641 */ | |
3642 renderCellNotThisMonth : function(workingDate, cell) { | |
3643 Dom.addClass(cell, this.Style.CSS_CELL_OOM); | |
3644 cell.innerHTML=workingDate.getDate(); | |
3645 return Calendar.STOP_RENDER; | |
3646 }, | |
3647 | |
3648 /** | |
3649 * Renders the current calendar cell as a non-selectable "black-out" date using the default | |
3650 * restricted style. | |
3651 * @method renderBodyCellRestricted | |
3652 * @param {Date} workingDate The current working Date object being used to generate the calendar | |
3653 * @param {HTMLTableCellElement} cell The current working cell in the calendar | |
3654 * @return {String} YAHOO.widget.Calendar.STOP_RENDER if rendering should stop with this style, null or nothing if rendering | |
3655 * should not be terminated | |
3656 */ | |
3657 renderBodyCellRestricted : function(workingDate, cell) { | |
3658 Dom.addClass(cell, this.Style.CSS_CELL); | |
3659 Dom.addClass(cell, this.Style.CSS_CELL_RESTRICTED); | |
3660 cell.innerHTML=workingDate.getDate(); | |
3661 return Calendar.STOP_RENDER; | |
3662 }, | |
3663 | |
3664 // END BUILT-IN TABLE CELL RENDERERS | |
3665 | |
3666 // BEGIN MONTH NAVIGATION METHODS | |
3667 | |
3668 /** | |
3669 * Adds the designated number of months to the current calendar month, and sets the current | |
3670 * calendar page date to the new month. | |
3671 * @method addMonths | |
3672 * @param {Number} count The number of months to add to the current calendar | |
3673 */ | |
3674 addMonths : function(count) { | |
3675 var cfgPageDate = DEF_CFG.PAGEDATE.key, | |
3676 | |
3677 prevDate = this.cfg.getProperty(cfgPageDate), | |
3678 newDate = DateMath.add(prevDate, DateMath.MONTH, count); | |
3679 | |
3680 this.cfg.setProperty(cfgPageDate, newDate); | |
3681 this.resetRenderers(); | |
3682 this.changePageEvent.fire(prevDate, newDate); | |
3683 }, | |
3684 | |
3685 /** | |
3686 * Subtracts the designated number of months from the current calendar month, and sets the current | |
3687 * calendar page date to the new month. | |
3688 * @method subtractMonths | |
3689 * @param {Number} count The number of months to subtract from the current calendar | |
3690 */ | |
3691 subtractMonths : function(count) { | |
3692 this.addMonths(-1*count); | |
3693 }, | |
3694 | |
3695 /** | |
3696 * Adds the designated number of years to the current calendar, and sets the current | |
3697 * calendar page date to the new month. | |
3698 * @method addYears | |
3699 * @param {Number} count The number of years to add to the current calendar | |
3700 */ | |
3701 addYears : function(count) { | |
3702 var cfgPageDate = DEF_CFG.PAGEDATE.key, | |
3703 | |
3704 prevDate = this.cfg.getProperty(cfgPageDate), | |
3705 newDate = DateMath.add(prevDate, DateMath.YEAR, count); | |
3706 | |
3707 this.cfg.setProperty(cfgPageDate, newDate); | |
3708 this.resetRenderers(); | |
3709 this.changePageEvent.fire(prevDate, newDate); | |
3710 }, | |
3711 | |
3712 /** | |
3713 * Subtcats the designated number of years from the current calendar, and sets the current | |
3714 * calendar page date to the new month. | |
3715 * @method subtractYears | |
3716 * @param {Number} count The number of years to subtract from the current calendar | |
3717 */ | |
3718 subtractYears : function(count) { | |
3719 this.addYears(-1*count); | |
3720 }, | |
3721 | |
3722 /** | |
3723 * Navigates to the next month page in the calendar widget. | |
3724 * @method nextMonth | |
3725 */ | |
3726 nextMonth : function() { | |
3727 this.addMonths(1); | |
3728 }, | |
3729 | |
3730 /** | |
3731 * Navigates to the previous month page in the calendar widget. | |
3732 * @method previousMonth | |
3733 */ | |
3734 previousMonth : function() { | |
3735 this.addMonths(-1); | |
3736 }, | |
3737 | |
3738 /** | |
3739 * Navigates to the next year in the currently selected month in the calendar widget. | |
3740 * @method nextYear | |
3741 */ | |
3742 nextYear : function() { | |
3743 this.addYears(1); | |
3744 }, | |
3745 | |
3746 /** | |
3747 * Navigates to the previous year in the currently selected month in the calendar widget. | |
3748 * @method previousYear | |
3749 */ | |
3750 previousYear : function() { | |
3751 this.addYears(-1); | |
3752 }, | |
3753 | |
3754 // END MONTH NAVIGATION METHODS | |
3755 | |
3756 // BEGIN SELECTION METHODS | |
3757 | |
3758 /** | |
3759 * Resets the calendar widget to the originally selected month and year, and | |
3760 * sets the calendar to the initial selection(s). | |
3761 * @method reset | |
3762 */ | |
3763 reset : function() { | |
3764 this.cfg.resetProperty(DEF_CFG.SELECTED.key); | |
3765 this.cfg.resetProperty(DEF_CFG.PAGEDATE.key); | |
3766 this.resetEvent.fire(); | |
3767 }, | |
3768 | |
3769 /** | |
3770 * Clears the selected dates in the current calendar widget and sets the calendar | |
3771 * to the current month and year. | |
3772 * @method clear | |
3773 */ | |
3774 clear : function() { | |
3775 this.cfg.setProperty(DEF_CFG.SELECTED.key, []); | |
3776 this.cfg.setProperty(DEF_CFG.PAGEDATE.key, new Date(this.today.getTime())); | |
3777 this.clearEvent.fire(); | |
3778 }, | |
3779 | |
3780 /** | |
3781 * Selects a date or a collection of dates on the current calendar. This method, by default, | |
3782 * does not call the render method explicitly. Once selection has completed, render must be | |
3783 * called for the changes to be reflected visually. | |
3784 * | |
3785 * Any dates which are OOB (out of bounds, not selectable) will not be selected and the array of | |
3786 * selected dates passed to the selectEvent will not contain OOB dates. | |
3787 * | |
3788 * If all dates are OOB, the no state change will occur; beforeSelect and select events will not be fired. | |
3789 * | |
3790 * @method select | |
3791 * @param {String/Date/Date[]} date The date string of dates to select in the current calendar. Valid formats are | |
3792 * individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006). | |
3793 * Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005). | |
3794 * This method can also take a JavaScript Date object or an array of Date objects. | |
3795 * @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected. | |
3796 */ | |
3797 select : function(date) { | |
3798 this.logger.log("Select: " + date, "info"); | |
3799 | |
3800 var aToBeSelected = this._toFieldArray(date), | |
3801 validDates = [], | |
3802 selected = [], | |
3803 cfgSelected = DEF_CFG.SELECTED.key; | |
3804 | |
3805 this.logger.log("Selection field array: " + aToBeSelected, "info"); | |
3806 | |
3807 for (var a=0; a < aToBeSelected.length; ++a) { | |
3808 var toSelect = aToBeSelected[a]; | |
3809 | |
3810 if (!this.isDateOOB(this._toDate(toSelect))) { | |
3811 | |
3812 if (validDates.length === 0) { | |
3813 this.beforeSelectEvent.fire(); | |
3814 selected = this.cfg.getProperty(cfgSelected); | |
3815 } | |
3816 validDates.push(toSelect); | |
3817 | |
3818 if (this._indexOfSelectedFieldArray(toSelect) == -1) { | |
3819 selected[selected.length] = toSelect; | |
3820 } | |
3821 } | |
3822 } | |
3823 | |
3824 if (validDates.length === 0) { this.logger.log("All provided dates were OOB. beforeSelect and select events not fired", "info"); } | |
3825 | |
3826 if (validDates.length > 0) { | |
3827 if (this.parent) { | |
3828 this.parent.cfg.setProperty(cfgSelected, selected); | |
3829 } else { | |
3830 this.cfg.setProperty(cfgSelected, selected); | |
3831 } | |
3832 this.selectEvent.fire(validDates); | |
3833 } | |
3834 | |
3835 return this.getSelectedDates(); | |
3836 }, | |
3837 | |
3838 /** | |
3839 * Selects a date on the current calendar by referencing the index of the cell that should be selected. | |
3840 * This method is used to easily select a single cell (usually with a mouse click) without having to do | |
3841 * a full render. The selected style is applied to the cell directly. | |
3842 * | |
3843 * If the cell is not marked with the CSS_CELL_SELECTABLE class (as is the case by default for out of month | |
3844 * or out of bounds cells), it will not be selected and in such a case beforeSelect and select events will not be fired. | |
3845 * | |
3846 * @method selectCell | |
3847 * @param {Number} cellIndex The index of the cell to select in the current calendar. | |
3848 * @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected. | |
3849 */ | |
3850 selectCell : function(cellIndex) { | |
3851 | |
3852 var cell = this.cells[cellIndex], | |
3853 cellDate = this.cellDates[cellIndex], | |
3854 dCellDate = this._toDate(cellDate), | |
3855 selectable = Dom.hasClass(cell, this.Style.CSS_CELL_SELECTABLE); | |
3856 | |
3857 this.logger.log("Select: " + dCellDate, "info"); | |
3858 if (!selectable) {this.logger.log("The cell at cellIndex:" + cellIndex + " is not a selectable cell. beforeSelect, select events not fired", "info"); } | |
3859 | |
3860 if (selectable) { | |
3861 | |
3862 this.beforeSelectEvent.fire(); | |
3863 | |
3864 var cfgSelected = DEF_CFG.SELECTED.key; | |
3865 var selected = this.cfg.getProperty(cfgSelected); | |
3866 | |
3867 var selectDate = cellDate.concat(); | |
3868 | |
3869 if (this._indexOfSelectedFieldArray(selectDate) == -1) { | |
3870 selected[selected.length] = selectDate; | |
3871 } | |
3872 if (this.parent) { | |
3873 this.parent.cfg.setProperty(cfgSelected, selected); | |
3874 } else { | |
3875 this.cfg.setProperty(cfgSelected, selected); | |
3876 } | |
3877 this.renderCellStyleSelected(dCellDate,cell); | |
3878 this.selectEvent.fire([selectDate]); | |
3879 | |
3880 this.doCellMouseOut.call(cell, null, this); | |
3881 } | |
3882 | |
3883 return this.getSelectedDates(); | |
3884 }, | |
3885 | |
3886 /** | |
3887 * Deselects a date or a collection of dates on the current calendar. This method, by default, | |
3888 * does not call the render method explicitly. Once deselection has completed, render must be | |
3889 * called for the changes to be reflected visually. | |
3890 * | |
3891 * The method will not attempt to deselect any dates which are OOB (out of bounds, and hence not selectable) | |
3892 * and the array of deselected dates passed to the deselectEvent will not contain any OOB dates. | |
3893 * | |
3894 * If all dates are OOB, beforeDeselect and deselect events will not be fired. | |
3895 * | |
3896 * @method deselect | |
3897 * @param {String/Date/Date[]} date The date string of dates to deselect in the current calendar. Valid formats are | |
3898 * individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006). | |
3899 * Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005). | |
3900 * This method can also take a JavaScript Date object or an array of Date objects. | |
3901 * @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected. | |
3902 */ | |
3903 deselect : function(date) { | |
3904 this.logger.log("Deselect: " + date, "info"); | |
3905 | |
3906 var aToBeDeselected = this._toFieldArray(date), | |
3907 validDates = [], | |
3908 selected = [], | |
3909 cfgSelected = DEF_CFG.SELECTED.key; | |
3910 | |
3911 this.logger.log("Deselection field array: " + aToBeDeselected, "info"); | |
3912 | |
3913 for (var a=0; a < aToBeDeselected.length; ++a) { | |
3914 var toDeselect = aToBeDeselected[a]; | |
3915 | |
3916 if (!this.isDateOOB(this._toDate(toDeselect))) { | |
3917 | |
3918 if (validDates.length === 0) { | |
3919 this.beforeDeselectEvent.fire(); | |
3920 selected = this.cfg.getProperty(cfgSelected); | |
3921 } | |
3922 | |
3923 validDates.push(toDeselect); | |
3924 | |
3925 var index = this._indexOfSelectedFieldArray(toDeselect); | |
3926 if (index != -1) { | |
3927 selected.splice(index,1); | |
3928 } | |
3929 } | |
3930 } | |
3931 | |
3932 if (validDates.length === 0) { this.logger.log("All provided dates were OOB. beforeDeselect and deselect events not fired");} | |
3933 | |
3934 if (validDates.length > 0) { | |
3935 if (this.parent) { | |
3936 this.parent.cfg.setProperty(cfgSelected, selected); | |
3937 } else { | |
3938 this.cfg.setProperty(cfgSelected, selected); | |
3939 } | |
3940 this.deselectEvent.fire(validDates); | |
3941 } | |
3942 | |
3943 return this.getSelectedDates(); | |
3944 }, | |
3945 | |
3946 /** | |
3947 * Deselects a date on the current calendar by referencing the index of the cell that should be deselected. | |
3948 * This method is used to easily deselect a single cell (usually with a mouse click) without having to do | |
3949 * a full render. The selected style is removed from the cell directly. | |
3950 * | |
3951 * If the cell is not marked with the CSS_CELL_SELECTABLE class (as is the case by default for out of month | |
3952 * or out of bounds cells), the method will not attempt to deselect it and in such a case, beforeDeselect and | |
3953 * deselect events will not be fired. | |
3954 * | |
3955 * @method deselectCell | |
3956 * @param {Number} cellIndex The index of the cell to deselect in the current calendar. | |
3957 * @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected. | |
3958 */ | |
3959 deselectCell : function(cellIndex) { | |
3960 var cell = this.cells[cellIndex], | |
3961 cellDate = this.cellDates[cellIndex], | |
3962 cellDateIndex = this._indexOfSelectedFieldArray(cellDate); | |
3963 | |
3964 var selectable = Dom.hasClass(cell, this.Style.CSS_CELL_SELECTABLE); | |
3965 if (!selectable) { this.logger.log("The cell at cellIndex:" + cellIndex + " is not a selectable/deselectable cell", "info"); } | |
3966 | |
3967 if (selectable) { | |
3968 | |
3969 this.beforeDeselectEvent.fire(); | |
3970 | |
3971 var selected = this.cfg.getProperty(DEF_CFG.SELECTED.key), | |
3972 dCellDate = this._toDate(cellDate), | |
3973 selectDate = cellDate.concat(); | |
3974 | |
3975 if (cellDateIndex > -1) { | |
3976 if (this.cfg.getProperty(DEF_CFG.PAGEDATE.key).getMonth() == dCellDate.getMonth() && | |
3977 this.cfg.getProperty(DEF_CFG.PAGEDATE.key).getFullYear() == dCellDate.getFullYear()) { | |
3978 Dom.removeClass(cell, this.Style.CSS_CELL_SELECTED); | |
3979 } | |
3980 selected.splice(cellDateIndex, 1); | |
3981 } | |
3982 | |
3983 if (this.parent) { | |
3984 this.parent.cfg.setProperty(DEF_CFG.SELECTED.key, selected); | |
3985 } else { | |
3986 this.cfg.setProperty(DEF_CFG.SELECTED.key, selected); | |
3987 } | |
3988 | |
3989 this.deselectEvent.fire([selectDate]); | |
3990 } | |
3991 | |
3992 return this.getSelectedDates(); | |
3993 }, | |
3994 | |
3995 /** | |
3996 * Deselects all dates on the current calendar. | |
3997 * @method deselectAll | |
3998 * @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected. | |
3999 * Assuming that this function executes properly, the return value should be an empty array. | |
4000 * However, the empty array is returned for the sake of being able to check the selection status | |
4001 * of the calendar. | |
4002 */ | |
4003 deselectAll : function() { | |
4004 this.beforeDeselectEvent.fire(); | |
4005 | |
4006 var cfgSelected = DEF_CFG.SELECTED.key, | |
4007 selected = this.cfg.getProperty(cfgSelected), | |
4008 count = selected.length, | |
4009 sel = selected.concat(); | |
4010 | |
4011 if (this.parent) { | |
4012 this.parent.cfg.setProperty(cfgSelected, []); | |
4013 } else { | |
4014 this.cfg.setProperty(cfgSelected, []); | |
4015 } | |
4016 | |
4017 if (count > 0) { | |
4018 this.deselectEvent.fire(sel); | |
4019 } | |
4020 | |
4021 return this.getSelectedDates(); | |
4022 }, | |
4023 | |
4024 // END SELECTION METHODS | |
4025 | |
4026 // BEGIN TYPE CONVERSION METHODS | |
4027 | |
4028 /** | |
4029 * Converts a date (either a JavaScript Date object, or a date string) to the internal data structure | |
4030 * used to represent dates: [[yyyy,mm,dd],[yyyy,mm,dd]]. | |
4031 * @method _toFieldArray | |
4032 * @private | |
4033 * @param {String/Date/Date[]} date The date string of dates to deselect in the current calendar. Valid formats are | |
4034 * individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006). | |
4035 * Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005). | |
4036 * This method can also take a JavaScript Date object or an array of Date objects. | |
4037 * @return {Array[](Number[])} Array of date field arrays | |
4038 */ | |
4039 _toFieldArray : function(date) { | |
4040 var returnDate = []; | |
4041 | |
4042 if (date instanceof Date) { | |
4043 returnDate = [[date.getFullYear(), date.getMonth()+1, date.getDate()]]; | |
4044 } else if (Lang.isString(date)) { | |
4045 returnDate = this._parseDates(date); | |
4046 } else if (Lang.isArray(date)) { | |
4047 for (var i=0;i<date.length;++i) { | |
4048 var d = date[i]; | |
4049 returnDate[returnDate.length] = [d.getFullYear(),d.getMonth()+1,d.getDate()]; | |
4050 } | |
4051 } | |
4052 | |
4053 return returnDate; | |
4054 }, | |
4055 | |
4056 /** | |
4057 * Converts a date field array [yyyy,mm,dd] to a JavaScript Date object. The date field array | |
4058 * is the format in which dates are as provided as arguments to selectEvent and deselectEvent listeners. | |
4059 * | |
4060 * @method toDate | |
4061 * @param {Number[]} dateFieldArray The date field array to convert to a JavaScript Date. | |
4062 * @return {Date} JavaScript Date object representing the date field array. | |
4063 */ | |
4064 toDate : function(dateFieldArray) { | |
4065 return this._toDate(dateFieldArray); | |
4066 }, | |
4067 | |
4068 /** | |
4069 * Converts a date field array [yyyy,mm,dd] to a JavaScript Date object. | |
4070 * @method _toDate | |
4071 * @private | |
4072 * @deprecated Made public, toDate | |
4073 * @param {Number[]} dateFieldArray The date field array to convert to a JavaScript Date. | |
4074 * @return {Date} JavaScript Date object representing the date field array | |
4075 */ | |
4076 _toDate : function(dateFieldArray) { | |
4077 if (dateFieldArray instanceof Date) { | |
4078 return dateFieldArray; | |
4079 } else { | |
4080 return DateMath.getDate(dateFieldArray[0],dateFieldArray[1]-1,dateFieldArray[2]); | |
4081 } | |
4082 }, | |
4083 | |
4084 // END TYPE CONVERSION METHODS | |
4085 | |
4086 // BEGIN UTILITY METHODS | |
4087 | |
4088 /** | |
4089 * Determines if 2 field arrays are equal. | |
4090 * @method _fieldArraysAreEqual | |
4091 * @private | |
4092 * @param {Number[]} array1 The first date field array to compare | |
4093 * @param {Number[]} array2 The first date field array to compare | |
4094 * @return {Boolean} The boolean that represents the equality of the two arrays | |
4095 */ | |
4096 _fieldArraysAreEqual : function(array1, array2) { | |
4097 var match = false; | |
4098 | |
4099 if (array1[0]==array2[0]&&array1[1]==array2[1]&&array1[2]==array2[2]) { | |
4100 match=true; | |
4101 } | |
4102 | |
4103 return match; | |
4104 }, | |
4105 | |
4106 /** | |
4107 * Gets the index of a date field array [yyyy,mm,dd] in the current list of selected dates. | |
4108 * @method _indexOfSelectedFieldArray | |
4109 * @private | |
4110 * @param {Number[]} find The date field array to search for | |
4111 * @return {Number} The index of the date field array within the collection of selected dates. | |
4112 * -1 will be returned if the date is not found. | |
4113 */ | |
4114 _indexOfSelectedFieldArray : function(find) { | |
4115 var selected = -1, | |
4116 seldates = this.cfg.getProperty(DEF_CFG.SELECTED.key); | |
4117 | |
4118 for (var s=0;s<seldates.length;++s) { | |
4119 var sArray = seldates[s]; | |
4120 if (find[0]==sArray[0]&&find[1]==sArray[1]&&find[2]==sArray[2]) { | |
4121 selected = s; | |
4122 break; | |
4123 } | |
4124 } | |
4125 | |
4126 return selected; | |
4127 }, | |
4128 | |
4129 /** | |
4130 * Determines whether a given date is OOM (out of month). | |
4131 * @method isDateOOM | |
4132 * @param {Date} date The JavaScript Date object for which to check the OOM status | |
4133 * @return {Boolean} true if the date is OOM | |
4134 */ | |
4135 isDateOOM : function(date) { | |
4136 return (date.getMonth() != this.cfg.getProperty(DEF_CFG.PAGEDATE.key).getMonth()); | |
4137 }, | |
4138 | |
4139 /** | |
4140 * Determines whether a given date is OOB (out of bounds - less than the mindate or more than the maxdate). | |
4141 * | |
4142 * @method isDateOOB | |
4143 * @param {Date} date The JavaScript Date object for which to check the OOB status | |
4144 * @return {Boolean} true if the date is OOB | |
4145 */ | |
4146 isDateOOB : function(date) { | |
4147 var minDate = this.cfg.getProperty(DEF_CFG.MINDATE.key), | |
4148 maxDate = this.cfg.getProperty(DEF_CFG.MAXDATE.key), | |
4149 dm = DateMath; | |
4150 | |
4151 if (minDate) { | |
4152 minDate = dm.clearTime(minDate); | |
4153 } | |
4154 if (maxDate) { | |
4155 maxDate = dm.clearTime(maxDate); | |
4156 } | |
4157 | |
4158 var clearedDate = new Date(date.getTime()); | |
4159 clearedDate = dm.clearTime(clearedDate); | |
4160 | |
4161 return ((minDate && clearedDate.getTime() < minDate.getTime()) || (maxDate && clearedDate.getTime() > maxDate.getTime())); | |
4162 }, | |
4163 | |
4164 /** | |
4165 * Parses a pagedate configuration property value. The value can either be specified as a string of form "mm/yyyy" or a Date object | |
4166 * 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 | |
4167 * @method _parsePageDate | |
4168 * @private | |
4169 * @param {Date|String} date Pagedate value which needs to be parsed | |
4170 * @return {Date} The Date object representing the pagedate | |
4171 */ | |
4172 _parsePageDate : function(date) { | |
4173 var parsedDate; | |
4174 | |
4175 if (date) { | |
4176 if (date instanceof Date) { | |
4177 parsedDate = DateMath.findMonthStart(date); | |
4178 } else { | |
4179 var month, year, aMonthYear; | |
4180 aMonthYear = date.split(this.cfg.getProperty(DEF_CFG.DATE_FIELD_DELIMITER.key)); | |
4181 month = parseInt(aMonthYear[this.cfg.getProperty(DEF_CFG.MY_MONTH_POSITION.key)-1], 10)-1; | |
4182 year = parseInt(aMonthYear[this.cfg.getProperty(DEF_CFG.MY_YEAR_POSITION.key)-1], 10) - this.Locale.YEAR_OFFSET; | |
4183 | |
4184 parsedDate = DateMath.getDate(year, month, 1); | |
4185 } | |
4186 } else { | |
4187 parsedDate = DateMath.getDate(this.today.getFullYear(), this.today.getMonth(), 1); | |
4188 } | |
4189 return parsedDate; | |
4190 }, | |
4191 | |
4192 // END UTILITY METHODS | |
4193 | |
4194 // BEGIN EVENT HANDLERS | |
4195 | |
4196 /** | |
4197 * Event executed before a date is selected in the calendar widget. | |
4198 * @deprecated Event handlers for this event should be susbcribed to beforeSelectEvent. | |
4199 */ | |
4200 onBeforeSelect : function() { | |
4201 if (this.cfg.getProperty(DEF_CFG.MULTI_SELECT.key) === false) { | |
4202 if (this.parent) { | |
4203 this.parent.callChildFunction("clearAllBodyCellStyles", this.Style.CSS_CELL_SELECTED); | |
4204 this.parent.deselectAll(); | |
4205 } else { | |
4206 this.clearAllBodyCellStyles(this.Style.CSS_CELL_SELECTED); | |
4207 this.deselectAll(); | |
4208 } | |
4209 } | |
4210 }, | |
4211 | |
4212 /** | |
4213 * Event executed when a date is selected in the calendar widget. | |
4214 * @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] ] | |
4215 * @deprecated Event handlers for this event should be susbcribed to selectEvent. | |
4216 */ | |
4217 onSelect : function(selected) { }, | |
4218 | |
4219 /** | |
4220 * Event executed before a date is deselected in the calendar widget. | |
4221 * @deprecated Event handlers for this event should be susbcribed to beforeDeselectEvent. | |
4222 */ | |
4223 onBeforeDeselect : function() { }, | |
4224 | |
4225 /** | |
4226 * Event executed when a date is deselected in the calendar widget. | |
4227 * @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] ] | |
4228 * @deprecated Event handlers for this event should be susbcribed to deselectEvent. | |
4229 */ | |
4230 onDeselect : function(deselected) { }, | |
4231 | |
4232 /** | |
4233 * Event executed when the user navigates to a different calendar page. | |
4234 * @deprecated Event handlers for this event should be susbcribed to changePageEvent. | |
4235 */ | |
4236 onChangePage : function() { | |
4237 this.render(); | |
4238 }, | |
4239 | |
4240 /** | |
4241 * Event executed when the calendar widget is rendered. | |
4242 * @deprecated Event handlers for this event should be susbcribed to renderEvent. | |
4243 */ | |
4244 onRender : function() { }, | |
4245 | |
4246 /** | |
4247 * Event executed when the calendar widget is reset to its original state. | |
4248 * @deprecated Event handlers for this event should be susbcribed to resetEvemt. | |
4249 */ | |
4250 onReset : function() { this.render(); }, | |
4251 | |
4252 /** | |
4253 * Event executed when the calendar widget is completely cleared to the current month with no selections. | |
4254 * @deprecated Event handlers for this event should be susbcribed to clearEvent. | |
4255 */ | |
4256 onClear : function() { this.render(); }, | |
4257 | |
4258 /** | |
4259 * Validates the calendar widget. This method has no default implementation | |
4260 * and must be extended by subclassing the widget. | |
4261 * @return Should return true if the widget validates, and false if | |
4262 * it doesn't. | |
4263 * @type Boolean | |
4264 */ | |
4265 validate : function() { return true; }, | |
4266 | |
4267 // END EVENT HANDLERS | |
4268 | |
4269 // BEGIN DATE PARSE METHODS | |
4270 | |
4271 /** | |
4272 * Converts a date string to a date field array | |
4273 * @private | |
4274 * @param {String} sDate Date string. Valid formats are mm/dd and mm/dd/yyyy. | |
4275 * @return A date field array representing the string passed to the method | |
4276 * @type Array[](Number[]) | |
4277 */ | |
4278 _parseDate : function(sDate) { | |
4279 var aDate = sDate.split(this.Locale.DATE_FIELD_DELIMITER), | |
4280 rArray; | |
4281 | |
4282 if (aDate.length == 2) { | |
4283 rArray = [aDate[this.Locale.MD_MONTH_POSITION-1],aDate[this.Locale.MD_DAY_POSITION-1]]; | |
4284 rArray.type = Calendar.MONTH_DAY; | |
4285 } else { | |
4286 rArray = [aDate[this.Locale.MDY_YEAR_POSITION-1] - this.Locale.YEAR_OFFSET, aDate[this.Locale.MDY_MONTH_POSITION-1],aDate[this.Locale.MDY_DAY_POSITION-1]]; | |
4287 rArray.type = Calendar.DATE; | |
4288 } | |
4289 | |
4290 for (var i=0;i<rArray.length;i++) { | |
4291 rArray[i] = parseInt(rArray[i], 10); | |
4292 } | |
4293 | |
4294 return rArray; | |
4295 }, | |
4296 | |
4297 /** | |
4298 * Converts a multi or single-date string to an array of date field arrays | |
4299 * @private | |
4300 * @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 | |
4301 * @return An array of date field arrays | |
4302 * @type Array[](Number[]) | |
4303 */ | |
4304 _parseDates : function(sDates) { | |
4305 var aReturn = [], | |
4306 aDates = sDates.split(this.Locale.DATE_DELIMITER); | |
4307 | |
4308 for (var d=0;d<aDates.length;++d) { | |
4309 var sDate = aDates[d]; | |
4310 | |
4311 if (sDate.indexOf(this.Locale.DATE_RANGE_DELIMITER) != -1) { | |
4312 // This is a range | |
4313 var aRange = sDate.split(this.Locale.DATE_RANGE_DELIMITER), | |
4314 dateStart = this._parseDate(aRange[0]), | |
4315 dateEnd = this._parseDate(aRange[1]), | |
4316 fullRange = this._parseRange(dateStart, dateEnd); | |
4317 | |
4318 aReturn = aReturn.concat(fullRange); | |
4319 } else { | |
4320 // This is not a range | |
4321 var aDate = this._parseDate(sDate); | |
4322 aReturn.push(aDate); | |
4323 } | |
4324 } | |
4325 return aReturn; | |
4326 }, | |
4327 | |
4328 /** | |
4329 * Converts a date range to the full list of included dates | |
4330 * @private | |
4331 * @param {Number[]} startDate Date field array representing the first date in the range | |
4332 * @param {Number[]} endDate Date field array representing the last date in the range | |
4333 * @return An array of date field arrays | |
4334 * @type Array[](Number[]) | |
4335 */ | |
4336 _parseRange : function(startDate, endDate) { | |
4337 var dCurrent = DateMath.add(DateMath.getDate(startDate[0],startDate[1]-1,startDate[2]),DateMath.DAY,1), | |
4338 dEnd = DateMath.getDate(endDate[0], endDate[1]-1, endDate[2]), | |
4339 results = []; | |
4340 | |
4341 results.push(startDate); | |
4342 while (dCurrent.getTime() <= dEnd.getTime()) { | |
4343 results.push([dCurrent.getFullYear(),dCurrent.getMonth()+1,dCurrent.getDate()]); | |
4344 dCurrent = DateMath.add(dCurrent,DateMath.DAY,1); | |
4345 } | |
4346 return results; | |
4347 }, | |
4348 | |
4349 // END DATE PARSE METHODS | |
4350 | |
4351 // BEGIN RENDERER METHODS | |
4352 | |
4353 /** | |
4354 * Resets the render stack of the current calendar to its original pre-render value. | |
4355 */ | |
4356 resetRenderers : function() { | |
4357 this.renderStack = this._renderStack.concat(); | |
4358 }, | |
4359 | |
4360 /** | |
4361 * Removes all custom renderers added to the Calendar through the addRenderer, addMonthRenderer and | |
4362 * addWeekdayRenderer methods. Calendar's render method needs to be called after removing renderers | |
4363 * to re-render the Calendar without custom renderers applied. | |
4364 */ | |
4365 removeRenderers : function() { | |
4366 this._renderStack = []; | |
4367 this.renderStack = []; | |
4368 }, | |
4369 | |
4370 /** | |
4371 * Clears the inner HTML, CSS class and style information from the specified cell. | |
4372 * @method clearElement | |
4373 * @param {HTMLTableCellElement} cell The cell to clear | |
4374 */ | |
4375 clearElement : function(cell) { | |
4376 cell.innerHTML = " "; | |
4377 cell.className=""; | |
4378 }, | |
4379 | |
4380 /** | |
4381 * Adds a renderer to the render stack. The function reference passed to this method will be executed | |
4382 * when a date cell matches the conditions specified in the date string for this renderer. | |
4383 * @method addRenderer | |
4384 * @param {String} sDates A date string to associate with the specified renderer. Valid formats | |
4385 * include date (12/24/2005), month/day (12/24), and range (12/1/2004-1/1/2005) | |
4386 * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer. | |
4387 */ | |
4388 addRenderer : function(sDates, fnRender) { | |
4389 var aDates = this._parseDates(sDates); | |
4390 for (var i=0;i<aDates.length;++i) { | |
4391 var aDate = aDates[i]; | |
4392 | |
4393 if (aDate.length == 2) { // this is either a range or a month/day combo | |
4394 if (aDate[0] instanceof Array) { // this is a range | |
4395 this._addRenderer(Calendar.RANGE,aDate,fnRender); | |
4396 } else { // this is a month/day combo | |
4397 this._addRenderer(Calendar.MONTH_DAY,aDate,fnRender); | |
4398 } | |
4399 } else if (aDate.length == 3) { | |
4400 this._addRenderer(Calendar.DATE,aDate,fnRender); | |
4401 } | |
4402 } | |
4403 }, | |
4404 | |
4405 /** | |
4406 * The private method used for adding cell renderers to the local render stack. | |
4407 * This method is called by other methods that set the renderer type prior to the method call. | |
4408 * @method _addRenderer | |
4409 * @private | |
4410 * @param {String} type The type string that indicates the type of date renderer being added. | |
4411 * Values are YAHOO.widget.Calendar.DATE, YAHOO.widget.Calendar.MONTH_DAY, YAHOO.widget.Calendar.WEEKDAY, | |
4412 * YAHOO.widget.Calendar.RANGE, YAHOO.widget.Calendar.MONTH | |
4413 * @param {Array} aDates An array of dates used to construct the renderer. The format varies based | |
4414 * on the renderer type | |
4415 * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer. | |
4416 */ | |
4417 _addRenderer : function(type, aDates, fnRender) { | |
4418 var add = [type,aDates,fnRender]; | |
4419 this.renderStack.unshift(add); | |
4420 this._renderStack = this.renderStack.concat(); | |
4421 }, | |
4422 | |
4423 /** | |
4424 * Adds a month to the render stack. The function reference passed to this method will be executed | |
4425 * when a date cell matches the month passed to this method. | |
4426 * @method addMonthRenderer | |
4427 * @param {Number} month The month (1-12) to associate with this renderer | |
4428 * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer. | |
4429 */ | |
4430 addMonthRenderer : function(month, fnRender) { | |
4431 this._addRenderer(Calendar.MONTH,[month],fnRender); | |
4432 }, | |
4433 | |
4434 /** | |
4435 * Adds a weekday to the render stack. The function reference passed to this method will be executed | |
4436 * when a date cell matches the weekday passed to this method. | |
4437 * @method addWeekdayRenderer | |
4438 * @param {Number} weekday The weekday (Sunday = 1, Monday = 2 ... Saturday = 7) to associate with this renderer | |
4439 * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer. | |
4440 */ | |
4441 addWeekdayRenderer : function(weekday, fnRender) { | |
4442 this._addRenderer(Calendar.WEEKDAY,[weekday],fnRender); | |
4443 }, | |
4444 | |
4445 // END RENDERER METHODS | |
4446 | |
4447 // BEGIN CSS METHODS | |
4448 | |
4449 /** | |
4450 * Removes all styles from all body cells in the current calendar table. | |
4451 * @method clearAllBodyCellStyles | |
4452 * @param {style} style The CSS class name to remove from all calendar body cells | |
4453 */ | |
4454 clearAllBodyCellStyles : function(style) { | |
4455 for (var c=0;c<this.cells.length;++c) { | |
4456 Dom.removeClass(this.cells[c],style); | |
4457 } | |
4458 }, | |
4459 | |
4460 // END CSS METHODS | |
4461 | |
4462 // BEGIN GETTER/SETTER METHODS | |
4463 /** | |
4464 * Sets the calendar's month explicitly | |
4465 * @method setMonth | |
4466 * @param {Number} month The numeric month, from 0 (January) to 11 (December) | |
4467 */ | |
4468 setMonth : function(month) { | |
4469 var cfgPageDate = DEF_CFG.PAGEDATE.key, | |
4470 current = this.cfg.getProperty(cfgPageDate); | |
4471 current.setMonth(parseInt(month, 10)); | |
4472 this.cfg.setProperty(cfgPageDate, current); | |
4473 }, | |
4474 | |
4475 /** | |
4476 * Sets the calendar's year explicitly. | |
4477 * @method setYear | |
4478 * @param {Number} year The numeric 4-digit year | |
4479 */ | |
4480 setYear : function(year) { | |
4481 var cfgPageDate = DEF_CFG.PAGEDATE.key, | |
4482 current = this.cfg.getProperty(cfgPageDate); | |
4483 | |
4484 current.setFullYear(parseInt(year, 10) - this.Locale.YEAR_OFFSET); | |
4485 this.cfg.setProperty(cfgPageDate, current); | |
4486 }, | |
4487 | |
4488 /** | |
4489 * Gets the list of currently selected dates from the calendar. | |
4490 * @method getSelectedDates | |
4491 * @return {Date[]} An array of currently selected JavaScript Date objects. | |
4492 */ | |
4493 getSelectedDates : function() { | |
4494 var returnDates = [], | |
4495 selected = this.cfg.getProperty(DEF_CFG.SELECTED.key); | |
4496 | |
4497 for (var d=0;d<selected.length;++d) { | |
4498 var dateArray = selected[d]; | |
4499 | |
4500 var date = DateMath.getDate(dateArray[0],dateArray[1]-1,dateArray[2]); | |
4501 returnDates.push(date); | |
4502 } | |
4503 | |
4504 returnDates.sort( function(a,b) { return a-b; } ); | |
4505 return returnDates; | |
4506 }, | |
4507 | |
4508 /// END GETTER/SETTER METHODS /// | |
4509 | |
4510 /** | |
4511 * Hides the Calendar's outer container from view. | |
4512 * @method hide | |
4513 */ | |
4514 hide : function() { | |
4515 if (this.beforeHideEvent.fire()) { | |
4516 this.oDomContainer.style.display = "none"; | |
4517 this.hideEvent.fire(); | |
4518 } | |
4519 }, | |
4520 | |
4521 /** | |
4522 * Shows the Calendar's outer container. | |
4523 * @method show | |
4524 */ | |
4525 show : function() { | |
4526 if (this.beforeShowEvent.fire()) { | |
4527 this.oDomContainer.style.display = "block"; | |
4528 this.showEvent.fire(); | |
4529 } | |
4530 }, | |
4531 | |
4532 /** | |
4533 * Returns a string representing the current browser. | |
4534 * @deprecated As of 2.3.0, environment information is available in YAHOO.env.ua | |
4535 * @see YAHOO.env.ua | |
4536 * @property browser | |
4537 * @type String | |
4538 */ | |
4539 browser : (function() { | |
4540 var ua = navigator.userAgent.toLowerCase(); | |
4541 if (ua.indexOf('opera')!=-1) { // Opera (check first in case of spoof) | |
4542 return 'opera'; | |
4543 } else if (ua.indexOf('msie 7')!=-1) { // IE7 | |
4544 return 'ie7'; | |
4545 } else if (ua.indexOf('msie') !=-1) { // IE | |
4546 return 'ie'; | |
4547 } else if (ua.indexOf('safari')!=-1) { // Safari (check before Gecko because it includes "like Gecko") | |
4548 return 'safari'; | |
4549 } else if (ua.indexOf('gecko') != -1) { // Gecko | |
4550 return 'gecko'; | |
4551 } else { | |
4552 return false; | |
4553 } | |
4554 })(), | |
4555 /** | |
4556 * Returns a string representation of the object. | |
4557 * @method toString | |
4558 * @return {String} A string representation of the Calendar object. | |
4559 */ | |
4560 toString : function() { | |
4561 return "Calendar " + this.id; | |
4562 }, | |
4563 | |
4564 /** | |
4565 * Destroys the Calendar instance. The method will remove references | |
4566 * to HTML elements, remove any event listeners added by the Calendar, | |
4567 * and destroy the Config and CalendarNavigator instances it has created. | |
4568 * | |
4569 * @method destroy | |
4570 */ | |
4571 destroy : function() { | |
4572 | |
4573 if (this.beforeDestroyEvent.fire()) { | |
4574 var cal = this; | |
4575 | |
4576 // Child objects | |
4577 if (cal.navigator) { | |
4578 cal.navigator.destroy(); | |
4579 } | |
4580 | |
4581 if (cal.cfg) { | |
4582 cal.cfg.destroy(); | |
4583 } | |
4584 | |
4585 // DOM event listeners | |
4586 Event.purgeElement(cal.oDomContainer, true); | |
4587 | |
4588 // Generated markup/DOM - Not removing the container DIV since we didn't create it. | |
4589 Dom.removeClass(cal.oDomContainer, cal.Style.CSS_WITH_TITLE); | |
4590 Dom.removeClass(cal.oDomContainer, cal.Style.CSS_CONTAINER); | |
4591 Dom.removeClass(cal.oDomContainer, cal.Style.CSS_SINGLE); | |
4592 cal.oDomContainer.innerHTML = ""; | |
4593 | |
4594 // JS-to-DOM references | |
4595 cal.oDomContainer = null; | |
4596 cal.cells = null; | |
4597 | |
4598 this.destroyEvent.fire(); | |
4599 } | |
4600 } | |
4601 }; | |
4602 | |
4603 YAHOO.widget.Calendar = Calendar; | |
4604 | |
4605 /** | |
4606 * @namespace YAHOO.widget | |
4607 * @class Calendar_Core | |
4608 * @extends YAHOO.widget.Calendar | |
4609 * @deprecated The old Calendar_Core class is no longer necessary. | |
4610 */ | |
4611 YAHOO.widget.Calendar_Core = YAHOO.widget.Calendar; | |
4612 | |
4613 YAHOO.widget.Cal_Core = YAHOO.widget.Calendar; | |
4614 | |
4615 })(); | |
4616 (function() { | |
4617 | |
4618 var Dom = YAHOO.util.Dom, | |
4619 DateMath = YAHOO.widget.DateMath, | |
4620 Event = YAHOO.util.Event, | |
4621 Lang = YAHOO.lang, | |
4622 Calendar = YAHOO.widget.Calendar; | |
4623 | |
4624 /** | |
4625 * YAHOO.widget.CalendarGroup is a special container class for YAHOO.widget.Calendar. This class facilitates | |
4626 * the ability to have multi-page calendar views that share a single dataset and are | |
4627 * dependent on each other. | |
4628 * | |
4629 * The calendar group instance will refer to each of its elements using a 0-based index. | |
4630 * For example, to construct the placeholder for a calendar group widget with id "cal1" and | |
4631 * containerId of "cal1Container", the markup would be as follows: | |
4632 * <xmp> | |
4633 * <div id="cal1Container_0"></div> | |
4634 * <div id="cal1Container_1"></div> | |
4635 * </xmp> | |
4636 * The tables for the calendars ("cal1_0" and "cal1_1") will be inserted into those containers. | |
4637 * | |
4638 * <p> | |
4639 * <strong>NOTE: As of 2.4.0, the constructor's ID argument is optional.</strong> | |
4640 * The CalendarGroup can be constructed by simply providing a container ID string, | |
4641 * or a reference to a container DIV HTMLElement (the element needs to exist | |
4642 * in the document). | |
4643 * | |
4644 * E.g.: | |
4645 * <xmp> | |
4646 * var c = new YAHOO.widget.CalendarGroup("calContainer", configOptions); | |
4647 * </xmp> | |
4648 * or: | |
4649 * <xmp> | |
4650 * var containerDiv = YAHOO.util.Dom.get("calContainer"); | |
4651 * var c = new YAHOO.widget.CalendarGroup(containerDiv, configOptions); | |
4652 * </xmp> | |
4653 * </p> | |
4654 * <p> | |
4655 * If not provided, the ID will be generated from the container DIV ID by adding an "_t" suffix. | |
4656 * 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". | |
4657 * </p> | |
4658 * | |
4659 * @namespace YAHOO.widget | |
4660 * @class CalendarGroup | |
4661 * @constructor | |
4662 * @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. | |
4663 * @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. | |
4664 * @param {Object} config optional The configuration object containing the initial configuration values for the CalendarGroup. | |
4665 */ | |
4666 function CalendarGroup(id, containerId, config) { | |
4667 if (arguments.length > 0) { | |
4668 this.init.apply(this, arguments); | |
4669 } | |
4670 } | |
4671 | |
4672 /** | |
4673 * The set of default Config property keys and values for the CalendarGroup. | |
4674 * | |
4675 * <p> | |
4676 * NOTE: This property is made public in order to allow users to change | |
4677 * the default values of configuration properties. Users should not | |
4678 * modify the key string, unless they are overriding the Calendar implementation | |
4679 * </p> | |
4680 * | |
4681 * @property YAHOO.widget.CalendarGroup.DEFAULT_CONFIG | |
4682 * @static | |
4683 * @type Object An object with key/value pairs, the key being the | |
4684 * uppercase configuration property name and the value being an objec | |
4685 * literal with a key string property, and a value property, specifying the | |
4686 * default value of the property | |
4687 */ | |
4688 | |
4689 /** | |
4690 * The set of default Config property keys and values for the CalendarGroup | |
4691 * @property YAHOO.widget.CalendarGroup._DEFAULT_CONFIG | |
4692 * @deprecated Made public. See the public DEFAULT_CONFIG property for details | |
4693 * @private | |
4694 * @static | |
4695 * @type Object | |
4696 */ | |
4697 CalendarGroup.DEFAULT_CONFIG = CalendarGroup._DEFAULT_CONFIG = Calendar.DEFAULT_CONFIG; | |
4698 CalendarGroup.DEFAULT_CONFIG.PAGES = {key:"pages", value:2}; | |
4699 | |
4700 var DEF_CFG = CalendarGroup.DEFAULT_CONFIG; | |
4701 | |
4702 CalendarGroup.prototype = { | |
4703 | |
4704 /** | |
4705 * Initializes the calendar group. All subclasses must call this method in order for the | |
4706 * group to be initialized properly. | |
4707 * @method init | |
4708 * @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. | |
4709 * @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. | |
4710 * @param {Object} config optional The configuration object containing the initial configuration values for the CalendarGroup. | |
4711 */ | |
4712 init : function(id, container, config) { | |
4713 | |
4714 // Normalize 2.4.0, pre 2.4.0 args | |
4715 var nArgs = this._parseArgs(arguments); | |
4716 | |
4717 id = nArgs.id; | |
4718 container = nArgs.container; | |
4719 config = nArgs.config; | |
4720 | |
4721 this.oDomContainer = Dom.get(container); | |
4722 if (!this.oDomContainer) { this.logger.log("Container not found in document.", "error"); } | |
4723 | |
4724 if (!this.oDomContainer.id) { | |
4725 this.oDomContainer.id = Dom.generateId(); | |
4726 } | |
4727 if (!id) { | |
4728 id = this.oDomContainer.id + "_t"; | |
4729 } | |
4730 | |
4731 /** | |
4732 * The unique id associated with the CalendarGroup | |
4733 * @property id | |
4734 * @type String | |
4735 */ | |
4736 this.id = id; | |
4737 | |
4738 /** | |
4739 * The unique id associated with the CalendarGroup container | |
4740 * @property containerId | |
4741 * @type String | |
4742 */ | |
4743 this.containerId = this.oDomContainer.id; | |
4744 | |
4745 this.logger = new YAHOO.widget.LogWriter("CalendarGroup " + this.id); | |
4746 this.initEvents(); | |
4747 this.initStyles(); | |
4748 | |
4749 /** | |
4750 * The collection of Calendar pages contained within the CalendarGroup | |
4751 * @property pages | |
4752 * @type YAHOO.widget.Calendar[] | |
4753 */ | |
4754 this.pages = []; | |
4755 | |
4756 Dom.addClass(this.oDomContainer, CalendarGroup.CSS_CONTAINER); | |
4757 Dom.addClass(this.oDomContainer, CalendarGroup.CSS_MULTI_UP); | |
4758 | |
4759 /** | |
4760 * The Config object used to hold the configuration variables for the CalendarGroup | |
4761 * @property cfg | |
4762 * @type YAHOO.util.Config | |
4763 */ | |
4764 this.cfg = new YAHOO.util.Config(this); | |
4765 | |
4766 /** | |
4767 * The local object which contains the CalendarGroup's options | |
4768 * @property Options | |
4769 * @type Object | |
4770 */ | |
4771 this.Options = {}; | |
4772 | |
4773 /** | |
4774 * The local object which contains the CalendarGroup's locale settings | |
4775 * @property Locale | |
4776 * @type Object | |
4777 */ | |
4778 this.Locale = {}; | |
4779 | |
4780 this.setupConfig(); | |
4781 | |
4782 if (config) { | |
4783 this.cfg.applyConfig(config, true); | |
4784 } | |
4785 | |
4786 this.cfg.fireQueue(); | |
4787 | |
4788 // OPERA HACK FOR MISWRAPPED FLOATS | |
4789 if (YAHOO.env.ua.opera){ | |
4790 this.renderEvent.subscribe(this._fixWidth, this, true); | |
4791 this.showEvent.subscribe(this._fixWidth, this, true); | |
4792 } | |
4793 | |
4794 this.logger.log("Initialized " + this.pages.length + "-page CalendarGroup", "info"); | |
4795 }, | |
4796 | |
4797 setupConfig : function() { | |
4798 | |
4799 var cfg = this.cfg; | |
4800 | |
4801 /** | |
4802 * The number of pages to include in the CalendarGroup. This value can only be set once, in the CalendarGroup's constructor arguments. | |
4803 * @config pages | |
4804 * @type Number | |
4805 * @default 2 | |
4806 */ | |
4807 cfg.addProperty(DEF_CFG.PAGES.key, { value:DEF_CFG.PAGES.value, validator:cfg.checkNumber, handler:this.configPages } ); | |
4808 | |
4809 /** | |
4810 * The positive or negative year offset from the Gregorian calendar year (assuming a January 1st rollover) to | |
4811 * be used when displaying or parsing dates. NOTE: All JS Date objects returned by methods, or expected as input by | |
4812 * methods will always represent the Gregorian year, in order to maintain date/month/week values. | |
4813 * | |
4814 * @config year_offset | |
4815 * @type Number | |
4816 * @default 0 | |
4817 */ | |
4818 cfg.addProperty(DEF_CFG.YEAR_OFFSET.key, { value:DEF_CFG.YEAR_OFFSET.value, handler: this.delegateConfig, supercedes:DEF_CFG.YEAR_OFFSET.supercedes, suppressEvent:true } ); | |
4819 | |
4820 /** | |
4821 * The date to use to represent "Today". | |
4822 * | |
4823 * @config today | |
4824 * @type Date | |
4825 * @default Today's date | |
4826 */ | |
4827 cfg.addProperty(DEF_CFG.TODAY.key, { value: new Date(DEF_CFG.TODAY.value.getTime()), supercedes:DEF_CFG.TODAY.supercedes, handler: this.configToday, suppressEvent:false } ); | |
4828 | |
4829 /** | |
4830 * The month/year representing the current visible Calendar date (mm/yyyy) | |
4831 * @config pagedate | |
4832 * @type String | Date | |
4833 * @default Today's date | |
4834 */ | |
4835 cfg.addProperty(DEF_CFG.PAGEDATE.key, { value: DEF_CFG.PAGEDATE.value || new Date(DEF_CFG.TODAY.value.getTime()), handler:this.configPageDate } ); | |
4836 | |
4837 /** | |
4838 * The date or range of dates representing the current Calendar selection | |
4839 * | |
4840 * @config selected | |
4841 * @type String | |
4842 * @default [] | |
4843 */ | |
4844 cfg.addProperty(DEF_CFG.SELECTED.key, { value:[], handler:this.configSelected } ); | |
4845 | |
4846 /** | |
4847 * The title to display above the CalendarGroup's month header | |
4848 * @config title | |
4849 * @type String | |
4850 * @default "" | |
4851 */ | |
4852 cfg.addProperty(DEF_CFG.TITLE.key, { value:DEF_CFG.TITLE.value, handler:this.configTitle } ); | |
4853 | |
4854 /** | |
4855 * Whether or not a close button should be displayed for this CalendarGroup | |
4856 * @config close | |
4857 * @type Boolean | |
4858 * @default false | |
4859 */ | |
4860 cfg.addProperty(DEF_CFG.CLOSE.key, { value:DEF_CFG.CLOSE.value, handler:this.configClose } ); | |
4861 | |
4862 /** | |
4863 * 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. | |
4864 * This property is enabled by default for IE6 and below. It is disabled by default for other browsers for performance reasons, but can be | |
4865 * enabled if required. | |
4866 * | |
4867 * @config iframe | |
4868 * @type Boolean | |
4869 * @default true for IE6 and below, false for all other browsers | |
4870 */ | |
4871 cfg.addProperty(DEF_CFG.IFRAME.key, { value:DEF_CFG.IFRAME.value, handler:this.configIframe, validator:cfg.checkBoolean } ); | |
4872 | |
4873 /** | |
4874 * The minimum selectable date in the current Calendar (mm/dd/yyyy) | |
4875 * @config mindate | |
4876 * @type String | Date | |
4877 * @default null | |
4878 */ | |
4879 cfg.addProperty(DEF_CFG.MINDATE.key, { value:DEF_CFG.MINDATE.value, handler:this.delegateConfig } ); | |
4880 | |
4881 /** | |
4882 * The maximum selectable date in the current Calendar (mm/dd/yyyy) | |
4883 * @config maxdate | |
4884 * @type String | Date | |
4885 * @default null | |
4886 */ | |
4887 cfg.addProperty(DEF_CFG.MAXDATE.key, { value:DEF_CFG.MAXDATE.value, handler:this.delegateConfig } ); | |
4888 | |
4889 // Options properties | |
4890 | |
4891 /** | |
4892 * True if the Calendar should allow multiple selections. False by default. | |
4893 * @config MULTI_SELECT | |
4894 * @type Boolean | |
4895 * @default false | |
4896 */ | |
4897 cfg.addProperty(DEF_CFG.MULTI_SELECT.key, { value:DEF_CFG.MULTI_SELECT.value, handler:this.delegateConfig, validator:cfg.checkBoolean } ); | |
4898 | |
4899 /** | |
4900 * The weekday the week begins on. Default is 0 (Sunday). | |
4901 * @config START_WEEKDAY | |
4902 * @type number | |
4903 * @default 0 | |
4904 */ | |
4905 cfg.addProperty(DEF_CFG.START_WEEKDAY.key, { value:DEF_CFG.START_WEEKDAY.value, handler:this.delegateConfig, validator:cfg.checkNumber } ); | |
4906 | |
4907 /** | |
4908 * True if the Calendar should show weekday labels. True by default. | |
4909 * @config SHOW_WEEKDAYS | |
4910 * @type Boolean | |
4911 * @default true | |
4912 */ | |
4913 cfg.addProperty(DEF_CFG.SHOW_WEEKDAYS.key, { value:DEF_CFG.SHOW_WEEKDAYS.value, handler:this.delegateConfig, validator:cfg.checkBoolean } ); | |
4914 | |
4915 /** | |
4916 * True if the Calendar should show week row headers. False by default. | |
4917 * @config SHOW_WEEK_HEADER | |
4918 * @type Boolean | |
4919 * @default false | |
4920 */ | |
4921 cfg.addProperty(DEF_CFG.SHOW_WEEK_HEADER.key,{ value:DEF_CFG.SHOW_WEEK_HEADER.value, handler:this.delegateConfig, validator:cfg.checkBoolean } ); | |
4922 | |
4923 /** | |
4924 * True if the Calendar should show week row footers. False by default. | |
4925 * @config SHOW_WEEK_FOOTER | |
4926 * @type Boolean | |
4927 * @default false | |
4928 */ | |
4929 cfg.addProperty(DEF_CFG.SHOW_WEEK_FOOTER.key,{ value:DEF_CFG.SHOW_WEEK_FOOTER.value, handler:this.delegateConfig, validator:cfg.checkBoolean } ); | |
4930 | |
4931 /** | |
4932 * True if the Calendar should suppress weeks that are not a part of the current month. False by default. | |
4933 * @config HIDE_BLANK_WEEKS | |
4934 * @type Boolean | |
4935 * @default false | |
4936 */ | |
4937 cfg.addProperty(DEF_CFG.HIDE_BLANK_WEEKS.key,{ value:DEF_CFG.HIDE_BLANK_WEEKS.value, handler:this.delegateConfig, validator:cfg.checkBoolean } ); | |
4938 | |
4939 /** | |
4940 * The image that should be used for the left navigation arrow. | |
4941 * @config NAV_ARROW_LEFT | |
4942 * @type String | |
4943 * @deprecated You can customize the image by overriding the default CSS class for the left arrow - "calnavleft" | |
4944 * @default null | |
4945 */ | |
4946 cfg.addProperty(DEF_CFG.NAV_ARROW_LEFT.key, { value:DEF_CFG.NAV_ARROW_LEFT.value, handler:this.delegateConfig } ); | |
4947 | |
4948 /** | |
4949 * The image that should be used for the right navigation arrow. | |
4950 * @config NAV_ARROW_RIGHT | |
4951 * @type String | |
4952 * @deprecated You can customize the image by overriding the default CSS class for the right arrow - "calnavright" | |
4953 * @default null | |
4954 */ | |
4955 cfg.addProperty(DEF_CFG.NAV_ARROW_RIGHT.key, { value:DEF_CFG.NAV_ARROW_RIGHT.value, handler:this.delegateConfig } ); | |
4956 | |
4957 // Locale properties | |
4958 | |
4959 /** | |
4960 * The short month labels for the current locale. | |
4961 * @config MONTHS_SHORT | |
4962 * @type String[] | |
4963 * @default ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] | |
4964 */ | |
4965 cfg.addProperty(DEF_CFG.MONTHS_SHORT.key, { value:DEF_CFG.MONTHS_SHORT.value, handler:this.delegateConfig } ); | |
4966 | |
4967 /** | |
4968 * The long month labels for the current locale. | |
4969 * @config MONTHS_LONG | |
4970 * @type String[] | |
4971 * @default ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" | |
4972 */ | |
4973 cfg.addProperty(DEF_CFG.MONTHS_LONG.key, { value:DEF_CFG.MONTHS_LONG.value, handler:this.delegateConfig } ); | |
4974 | |
4975 /** | |
4976 * The 1-character weekday labels for the current locale. | |
4977 * @config WEEKDAYS_1CHAR | |
4978 * @type String[] | |
4979 * @default ["S", "M", "T", "W", "T", "F", "S"] | |
4980 */ | |
4981 cfg.addProperty(DEF_CFG.WEEKDAYS_1CHAR.key, { value:DEF_CFG.WEEKDAYS_1CHAR.value, handler:this.delegateConfig } ); | |
4982 | |
4983 /** | |
4984 * The short weekday labels for the current locale. | |
4985 * @config WEEKDAYS_SHORT | |
4986 * @type String[] | |
4987 * @default ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"] | |
4988 */ | |
4989 cfg.addProperty(DEF_CFG.WEEKDAYS_SHORT.key, { value:DEF_CFG.WEEKDAYS_SHORT.value, handler:this.delegateConfig } ); | |
4990 | |
4991 /** | |
4992 * The medium weekday labels for the current locale. | |
4993 * @config WEEKDAYS_MEDIUM | |
4994 * @type String[] | |
4995 * @default ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] | |
4996 */ | |
4997 cfg.addProperty(DEF_CFG.WEEKDAYS_MEDIUM.key, { value:DEF_CFG.WEEKDAYS_MEDIUM.value, handler:this.delegateConfig } ); | |
4998 | |
4999 /** | |
5000 * The long weekday labels for the current locale. | |
5001 * @config WEEKDAYS_LONG | |
5002 * @type String[] | |
5003 * @default ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] | |
5004 */ | |
5005 cfg.addProperty(DEF_CFG.WEEKDAYS_LONG.key, { value:DEF_CFG.WEEKDAYS_LONG.value, handler:this.delegateConfig } ); | |
5006 | |
5007 /** | |
5008 * The setting that determines which length of month labels should be used. Possible values are "short" and "long". | |
5009 * @config LOCALE_MONTHS | |
5010 * @type String | |
5011 * @default "long" | |
5012 */ | |
5013 cfg.addProperty(DEF_CFG.LOCALE_MONTHS.key, { value:DEF_CFG.LOCALE_MONTHS.value, handler:this.delegateConfig } ); | |
5014 | |
5015 /** | |
5016 * The setting that determines which length of weekday labels should be used. Possible values are "1char", "short", "medium", and "long". | |
5017 * @config LOCALE_WEEKDAYS | |
5018 * @type String | |
5019 * @default "short" | |
5020 */ | |
5021 cfg.addProperty(DEF_CFG.LOCALE_WEEKDAYS.key, { value:DEF_CFG.LOCALE_WEEKDAYS.value, handler:this.delegateConfig } ); | |
5022 | |
5023 /** | |
5024 * The value used to delimit individual dates in a date string passed to various Calendar functions. | |
5025 * @config DATE_DELIMITER | |
5026 * @type String | |
5027 * @default "," | |
5028 */ | |
5029 cfg.addProperty(DEF_CFG.DATE_DELIMITER.key, { value:DEF_CFG.DATE_DELIMITER.value, handler:this.delegateConfig } ); | |
5030 | |
5031 /** | |
5032 * The value used to delimit date fields in a date string passed to various Calendar functions. | |
5033 * @config DATE_FIELD_DELIMITER | |
5034 * @type String | |
5035 * @default "/" | |
5036 */ | |
5037 cfg.addProperty(DEF_CFG.DATE_FIELD_DELIMITER.key,{ value:DEF_CFG.DATE_FIELD_DELIMITER.value, handler:this.delegateConfig } ); | |
5038 | |
5039 /** | |
5040 * The value used to delimit date ranges in a date string passed to various Calendar functions. | |
5041 * @config DATE_RANGE_DELIMITER | |
5042 * @type String | |
5043 * @default "-" | |
5044 */ | |
5045 cfg.addProperty(DEF_CFG.DATE_RANGE_DELIMITER.key,{ value:DEF_CFG.DATE_RANGE_DELIMITER.value, handler:this.delegateConfig } ); | |
5046 | |
5047 /** | |
5048 * The position of the month in a month/year date string | |
5049 * @config MY_MONTH_POSITION | |
5050 * @type Number | |
5051 * @default 1 | |
5052 */ | |
5053 cfg.addProperty(DEF_CFG.MY_MONTH_POSITION.key, { value:DEF_CFG.MY_MONTH_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } ); | |
5054 | |
5055 /** | |
5056 * The position of the year in a month/year date string | |
5057 * @config MY_YEAR_POSITION | |
5058 * @type Number | |
5059 * @default 2 | |
5060 */ | |
5061 cfg.addProperty(DEF_CFG.MY_YEAR_POSITION.key, { value:DEF_CFG.MY_YEAR_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } ); | |
5062 | |
5063 /** | |
5064 * The position of the month in a month/day date string | |
5065 * @config MD_MONTH_POSITION | |
5066 * @type Number | |
5067 * @default 1 | |
5068 */ | |
5069 cfg.addProperty(DEF_CFG.MD_MONTH_POSITION.key, { value:DEF_CFG.MD_MONTH_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } ); | |
5070 | |
5071 /** | |
5072 * The position of the day in a month/year date string | |
5073 * @config MD_DAY_POSITION | |
5074 * @type Number | |
5075 * @default 2 | |
5076 */ | |
5077 cfg.addProperty(DEF_CFG.MD_DAY_POSITION.key, { value:DEF_CFG.MD_DAY_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } ); | |
5078 | |
5079 /** | |
5080 * The position of the month in a month/day/year date string | |
5081 * @config MDY_MONTH_POSITION | |
5082 * @type Number | |
5083 * @default 1 | |
5084 */ | |
5085 cfg.addProperty(DEF_CFG.MDY_MONTH_POSITION.key, { value:DEF_CFG.MDY_MONTH_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } ); | |
5086 | |
5087 /** | |
5088 * The position of the day in a month/day/year date string | |
5089 * @config MDY_DAY_POSITION | |
5090 * @type Number | |
5091 * @default 2 | |
5092 */ | |
5093 cfg.addProperty(DEF_CFG.MDY_DAY_POSITION.key, { value:DEF_CFG.MDY_DAY_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } ); | |
5094 | |
5095 /** | |
5096 * The position of the year in a month/day/year date string | |
5097 * @config MDY_YEAR_POSITION | |
5098 * @type Number | |
5099 * @default 3 | |
5100 */ | |
5101 cfg.addProperty(DEF_CFG.MDY_YEAR_POSITION.key, { value:DEF_CFG.MDY_YEAR_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } ); | |
5102 | |
5103 /** | |
5104 * The position of the month in the month year label string used as the Calendar header | |
5105 * @config MY_LABEL_MONTH_POSITION | |
5106 * @type Number | |
5107 * @default 1 | |
5108 */ | |
5109 cfg.addProperty(DEF_CFG.MY_LABEL_MONTH_POSITION.key, { value:DEF_CFG.MY_LABEL_MONTH_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } ); | |
5110 | |
5111 /** | |
5112 * The position of the year in the month year label string used as the Calendar header | |
5113 * @config MY_LABEL_YEAR_POSITION | |
5114 * @type Number | |
5115 * @default 2 | |
5116 */ | |
5117 cfg.addProperty(DEF_CFG.MY_LABEL_YEAR_POSITION.key, { value:DEF_CFG.MY_LABEL_YEAR_POSITION.value, handler:this.delegateConfig, validator:cfg.checkNumber } ); | |
5118 | |
5119 /** | |
5120 * The suffix used after the month when rendering the Calendar header | |
5121 * @config MY_LABEL_MONTH_SUFFIX | |
5122 * @type String | |
5123 * @default " " | |
5124 */ | |
5125 cfg.addProperty(DEF_CFG.MY_LABEL_MONTH_SUFFIX.key, { value:DEF_CFG.MY_LABEL_MONTH_SUFFIX.value, handler:this.delegateConfig } ); | |
5126 | |
5127 /** | |
5128 * The suffix used after the year when rendering the Calendar header | |
5129 * @config MY_LABEL_YEAR_SUFFIX | |
5130 * @type String | |
5131 * @default "" | |
5132 */ | |
5133 cfg.addProperty(DEF_CFG.MY_LABEL_YEAR_SUFFIX.key, { value:DEF_CFG.MY_LABEL_YEAR_SUFFIX.value, handler:this.delegateConfig } ); | |
5134 | |
5135 /** | |
5136 * Configuration for the Month Year Navigation UI. By default it is disabled | |
5137 * @config NAV | |
5138 * @type Object | |
5139 * @default null | |
5140 */ | |
5141 cfg.addProperty(DEF_CFG.NAV.key, { value:DEF_CFG.NAV.value, handler:this.configNavigator } ); | |
5142 | |
5143 /** | |
5144 * The map of UI strings which the CalendarGroup UI uses. | |
5145 * | |
5146 * @config strings | |
5147 * @type {Object} | |
5148 * @default An object with the properties shown below: | |
5149 * <dl> | |
5150 * <dt>previousMonth</dt><dd><em>String</em> : The string to use for the "Previous Month" navigation UI. Defaults to "Previous Month".</dd> | |
5151 * <dt>nextMonth</dt><dd><em>String</em> : The string to use for the "Next Month" navigation UI. Defaults to "Next Month".</dd> | |
5152 * <dt>close</dt><dd><em>String</em> : The string to use for the close button label. Defaults to "Close".</dd> | |
5153 * </dl> | |
5154 */ | |
5155 cfg.addProperty(DEF_CFG.STRINGS.key, { | |
5156 value:DEF_CFG.STRINGS.value, | |
5157 handler:this.configStrings, | |
5158 validator: function(val) { | |
5159 return Lang.isObject(val); | |
5160 }, | |
5161 supercedes: DEF_CFG.STRINGS.supercedes | |
5162 }); | |
5163 }, | |
5164 | |
5165 /** | |
5166 * Initializes CalendarGroup's built-in CustomEvents | |
5167 * @method initEvents | |
5168 */ | |
5169 initEvents : function() { | |
5170 | |
5171 var me = this, | |
5172 strEvent = "Event", | |
5173 CE = YAHOO.util.CustomEvent; | |
5174 | |
5175 /** | |
5176 * Proxy subscriber to subscribe to the CalendarGroup's child Calendars' CustomEvents | |
5177 * @method sub | |
5178 * @private | |
5179 * @param {Function} fn The function to subscribe to this CustomEvent | |
5180 * @param {Object} obj The CustomEvent's scope object | |
5181 * @param {Boolean} bOverride Whether or not to apply scope correction | |
5182 */ | |
5183 var sub = function(fn, obj, bOverride) { | |
5184 for (var p=0;p<me.pages.length;++p) { | |
5185 var cal = me.pages[p]; | |
5186 cal[this.type + strEvent].subscribe(fn, obj, bOverride); | |
5187 } | |
5188 }; | |
5189 | |
5190 /** | |
5191 * Proxy unsubscriber to unsubscribe from the CalendarGroup's child Calendars' CustomEvents | |
5192 * @method unsub | |
5193 * @private | |
5194 * @param {Function} fn The function to subscribe to this CustomEvent | |
5195 * @param {Object} obj The CustomEvent's scope object | |
5196 */ | |
5197 var unsub = function(fn, obj) { | |
5198 for (var p=0;p<me.pages.length;++p) { | |
5199 var cal = me.pages[p]; | |
5200 cal[this.type + strEvent].unsubscribe(fn, obj); | |
5201 } | |
5202 }; | |
5203 | |
5204 var defEvents = Calendar._EVENT_TYPES; | |
5205 | |
5206 /** | |
5207 * Fired before a date selection is made | |
5208 * @event beforeSelectEvent | |
5209 */ | |
5210 me.beforeSelectEvent = new CE(defEvents.BEFORE_SELECT); | |
5211 me.beforeSelectEvent.subscribe = sub; me.beforeSelectEvent.unsubscribe = unsub; | |
5212 | |
5213 /** | |
5214 * Fired when a date selection is made | |
5215 * @event selectEvent | |
5216 * @param {Array} Array of Date field arrays in the format [YYYY, MM, DD]. | |
5217 */ | |
5218 me.selectEvent = new CE(defEvents.SELECT); | |
5219 me.selectEvent.subscribe = sub; me.selectEvent.unsubscribe = unsub; | |
5220 | |
5221 /** | |
5222 * Fired before a date or set of dates is deselected | |
5223 * @event beforeDeselectEvent | |
5224 */ | |
5225 me.beforeDeselectEvent = new CE(defEvents.BEFORE_DESELECT); | |
5226 me.beforeDeselectEvent.subscribe = sub; me.beforeDeselectEvent.unsubscribe = unsub; | |
5227 | |
5228 /** | |
5229 * Fired when a date or set of dates has been deselected | |
5230 * @event deselectEvent | |
5231 * @param {Array} Array of Date field arrays in the format [YYYY, MM, DD]. | |
5232 */ | |
5233 me.deselectEvent = new CE(defEvents.DESELECT); | |
5234 me.deselectEvent.subscribe = sub; me.deselectEvent.unsubscribe = unsub; | |
5235 | |
5236 /** | |
5237 * Fired when the Calendar page is changed | |
5238 * @event changePageEvent | |
5239 */ | |
5240 me.changePageEvent = new CE(defEvents.CHANGE_PAGE); | |
5241 me.changePageEvent.subscribe = sub; me.changePageEvent.unsubscribe = unsub; | |
5242 | |
5243 /** | |
5244 * Fired before the Calendar is rendered | |
5245 * @event beforeRenderEvent | |
5246 */ | |
5247 me.beforeRenderEvent = new CE(defEvents.BEFORE_RENDER); | |
5248 me.beforeRenderEvent.subscribe = sub; me.beforeRenderEvent.unsubscribe = unsub; | |
5249 | |
5250 /** | |
5251 * Fired when the Calendar is rendered | |
5252 * @event renderEvent | |
5253 */ | |
5254 me.renderEvent = new CE(defEvents.RENDER); | |
5255 me.renderEvent.subscribe = sub; me.renderEvent.unsubscribe = unsub; | |
5256 | |
5257 /** | |
5258 * Fired when the Calendar is reset | |
5259 * @event resetEvent | |
5260 */ | |
5261 me.resetEvent = new CE(defEvents.RESET); | |
5262 me.resetEvent.subscribe = sub; me.resetEvent.unsubscribe = unsub; | |
5263 | |
5264 /** | |
5265 * Fired when the Calendar is cleared | |
5266 * @event clearEvent | |
5267 */ | |
5268 me.clearEvent = new CE(defEvents.CLEAR); | |
5269 me.clearEvent.subscribe = sub; me.clearEvent.unsubscribe = unsub; | |
5270 | |
5271 /** | |
5272 * Fired just before the CalendarGroup is to be shown | |
5273 * @event beforeShowEvent | |
5274 */ | |
5275 me.beforeShowEvent = new CE(defEvents.BEFORE_SHOW); | |
5276 | |
5277 /** | |
5278 * Fired after the CalendarGroup is shown | |
5279 * @event showEvent | |
5280 */ | |
5281 me.showEvent = new CE(defEvents.SHOW); | |
5282 | |
5283 /** | |
5284 * Fired just before the CalendarGroup is to be hidden | |
5285 * @event beforeHideEvent | |
5286 */ | |
5287 me.beforeHideEvent = new CE(defEvents.BEFORE_HIDE); | |
5288 | |
5289 /** | |
5290 * Fired after the CalendarGroup is hidden | |
5291 * @event hideEvent | |
5292 */ | |
5293 me.hideEvent = new CE(defEvents.HIDE); | |
5294 | |
5295 /** | |
5296 * Fired just before the CalendarNavigator is to be shown | |
5297 * @event beforeShowNavEvent | |
5298 */ | |
5299 me.beforeShowNavEvent = new CE(defEvents.BEFORE_SHOW_NAV); | |
5300 | |
5301 /** | |
5302 * Fired after the CalendarNavigator is shown | |
5303 * @event showNavEvent | |
5304 */ | |
5305 me.showNavEvent = new CE(defEvents.SHOW_NAV); | |
5306 | |
5307 /** | |
5308 * Fired just before the CalendarNavigator is to be hidden | |
5309 * @event beforeHideNavEvent | |
5310 */ | |
5311 me.beforeHideNavEvent = new CE(defEvents.BEFORE_HIDE_NAV); | |
5312 | |
5313 /** | |
5314 * Fired after the CalendarNavigator is hidden | |
5315 * @event hideNavEvent | |
5316 */ | |
5317 me.hideNavEvent = new CE(defEvents.HIDE_NAV); | |
5318 | |
5319 /** | |
5320 * Fired just before the CalendarNavigator is to be rendered | |
5321 * @event beforeRenderNavEvent | |
5322 */ | |
5323 me.beforeRenderNavEvent = new CE(defEvents.BEFORE_RENDER_NAV); | |
5324 | |
5325 /** | |
5326 * Fired after the CalendarNavigator is rendered | |
5327 * @event renderNavEvent | |
5328 */ | |
5329 me.renderNavEvent = new CE(defEvents.RENDER_NAV); | |
5330 | |
5331 /** | |
5332 * Fired just before the CalendarGroup is to be destroyed | |
5333 * @event beforeDestroyEvent | |
5334 */ | |
5335 me.beforeDestroyEvent = new CE(defEvents.BEFORE_DESTROY); | |
5336 | |
5337 /** | |
5338 * Fired after the CalendarGroup is destroyed. This event should be used | |
5339 * for notification only. When this event is fired, important CalendarGroup instance | |
5340 * properties, dom references and event listeners have already been | |
5341 * removed/dereferenced, and hence the CalendarGroup instance is not in a usable | |
5342 * state. | |
5343 * | |
5344 * @event destroyEvent | |
5345 */ | |
5346 me.destroyEvent = new CE(defEvents.DESTROY); | |
5347 }, | |
5348 | |
5349 /** | |
5350 * The default Config handler for the "pages" property | |
5351 * @method configPages | |
5352 * @param {String} type The CustomEvent type (usually the property name) | |
5353 * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. | |
5354 * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. | |
5355 */ | |
5356 configPages : function(type, args, obj) { | |
5357 var pageCount = args[0], | |
5358 cfgPageDate = DEF_CFG.PAGEDATE.key, | |
5359 sep = "_", | |
5360 caldate, | |
5361 firstPageDate = null, | |
5362 groupCalClass = "groupcal", | |
5363 firstClass = "first-of-type", | |
5364 lastClass = "last-of-type"; | |
5365 | |
5366 for (var p=0;p<pageCount;++p) { | |
5367 var calId = this.id + sep + p, | |
5368 calContainerId = this.containerId + sep + p, | |
5369 childConfig = this.cfg.getConfig(); | |
5370 | |
5371 childConfig.close = false; | |
5372 childConfig.title = false; | |
5373 childConfig.navigator = null; | |
5374 | |
5375 if (p > 0) { | |
5376 caldate = new Date(firstPageDate); | |
5377 this._setMonthOnDate(caldate, caldate.getMonth() + p); | |
5378 childConfig.pageDate = caldate; | |
5379 } | |
5380 | |
5381 var cal = this.constructChild(calId, calContainerId, childConfig); | |
5382 | |
5383 Dom.removeClass(cal.oDomContainer, this.Style.CSS_SINGLE); | |
5384 Dom.addClass(cal.oDomContainer, groupCalClass); | |
5385 | |
5386 if (p===0) { | |
5387 firstPageDate = cal.cfg.getProperty(cfgPageDate); | |
5388 Dom.addClass(cal.oDomContainer, firstClass); | |
5389 } | |
5390 | |
5391 if (p==(pageCount-1)) { | |
5392 Dom.addClass(cal.oDomContainer, lastClass); | |
5393 } | |
5394 | |
5395 cal.parent = this; | |
5396 cal.index = p; | |
5397 | |
5398 this.pages[this.pages.length] = cal; | |
5399 } | |
5400 }, | |
5401 | |
5402 /** | |
5403 * The default Config handler for the "pagedate" property | |
5404 * @method configPageDate | |
5405 * @param {String} type The CustomEvent type (usually the property name) | |
5406 * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. | |
5407 * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. | |
5408 */ | |
5409 configPageDate : function(type, args, obj) { | |
5410 var val = args[0], | |
5411 firstPageDate; | |
5412 | |
5413 var cfgPageDate = DEF_CFG.PAGEDATE.key; | |
5414 | |
5415 for (var p=0;p<this.pages.length;++p) { | |
5416 var cal = this.pages[p]; | |
5417 if (p === 0) { | |
5418 firstPageDate = cal._parsePageDate(val); | |
5419 cal.cfg.setProperty(cfgPageDate, firstPageDate); | |
5420 } else { | |
5421 var pageDate = new Date(firstPageDate); | |
5422 this._setMonthOnDate(pageDate, pageDate.getMonth() + p); | |
5423 cal.cfg.setProperty(cfgPageDate, pageDate); | |
5424 } | |
5425 } | |
5426 }, | |
5427 | |
5428 /** | |
5429 * The default Config handler for the CalendarGroup "selected" property | |
5430 * @method configSelected | |
5431 * @param {String} type The CustomEvent type (usually the property name) | |
5432 * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. | |
5433 * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. | |
5434 */ | |
5435 configSelected : function(type, args, obj) { | |
5436 var cfgSelected = DEF_CFG.SELECTED.key; | |
5437 this.delegateConfig(type, args, obj); | |
5438 var selected = (this.pages.length > 0) ? this.pages[0].cfg.getProperty(cfgSelected) : []; | |
5439 this.cfg.setProperty(cfgSelected, selected, true); | |
5440 }, | |
5441 | |
5442 | |
5443 /** | |
5444 * Delegates a configuration property to the CustomEvents associated with the CalendarGroup's children | |
5445 * @method delegateConfig | |
5446 * @param {String} type The CustomEvent type (usually the property name) | |
5447 * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. | |
5448 * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. | |
5449 */ | |
5450 delegateConfig : function(type, args, obj) { | |
5451 var val = args[0]; | |
5452 var cal; | |
5453 | |
5454 for (var p=0;p<this.pages.length;p++) { | |
5455 cal = this.pages[p]; | |
5456 cal.cfg.setProperty(type, val); | |
5457 } | |
5458 }, | |
5459 | |
5460 /** | |
5461 * Adds a function to all child Calendars within this CalendarGroup. | |
5462 * @method setChildFunction | |
5463 * @param {String} fnName The name of the function | |
5464 * @param {Function} fn The function to apply to each Calendar page object | |
5465 */ | |
5466 setChildFunction : function(fnName, fn) { | |
5467 var pageCount = this.cfg.getProperty(DEF_CFG.PAGES.key); | |
5468 | |
5469 for (var p=0;p<pageCount;++p) { | |
5470 this.pages[p][fnName] = fn; | |
5471 } | |
5472 }, | |
5473 | |
5474 /** | |
5475 * Calls a function within all child Calendars within this CalendarGroup. | |
5476 * @method callChildFunction | |
5477 * @param {String} fnName The name of the function | |
5478 * @param {Array} args The arguments to pass to the function | |
5479 */ | |
5480 callChildFunction : function(fnName, args) { | |
5481 var pageCount = this.cfg.getProperty(DEF_CFG.PAGES.key); | |
5482 | |
5483 for (var p=0;p<pageCount;++p) { | |
5484 var page = this.pages[p]; | |
5485 if (page[fnName]) { | |
5486 var fn = page[fnName]; | |
5487 fn.call(page, args); | |
5488 } | |
5489 } | |
5490 }, | |
5491 | |
5492 /** | |
5493 * Constructs a child calendar. This method can be overridden if a subclassed version of the default | |
5494 * calendar is to be used. | |
5495 * @method constructChild | |
5496 * @param {String} id The id of the table element that will represent the calendar widget | |
5497 * @param {String} containerId The id of the container div element that will wrap the calendar table | |
5498 * @param {Object} config The configuration object containing the Calendar's arguments | |
5499 * @return {YAHOO.widget.Calendar} The YAHOO.widget.Calendar instance that is constructed | |
5500 */ | |
5501 constructChild : function(id,containerId,config) { | |
5502 var container = document.getElementById(containerId); | |
5503 if (! container) { | |
5504 container = document.createElement("div"); | |
5505 container.id = containerId; | |
5506 this.oDomContainer.appendChild(container); | |
5507 } | |
5508 return new Calendar(id,containerId,config); | |
5509 }, | |
5510 | |
5511 /** | |
5512 * Sets the calendar group's month explicitly. This month will be set into the first | |
5513 * page of the multi-page calendar, and all other months will be iterated appropriately. | |
5514 * @method setMonth | |
5515 * @param {Number} month The numeric month, from 0 (January) to 11 (December) | |
5516 */ | |
5517 setMonth : function(month) { | |
5518 month = parseInt(month, 10); | |
5519 var currYear; | |
5520 | |
5521 var cfgPageDate = DEF_CFG.PAGEDATE.key; | |
5522 | |
5523 for (var p=0; p<this.pages.length; ++p) { | |
5524 var cal = this.pages[p]; | |
5525 var pageDate = cal.cfg.getProperty(cfgPageDate); | |
5526 if (p === 0) { | |
5527 currYear = pageDate.getFullYear(); | |
5528 } else { | |
5529 pageDate.setFullYear(currYear); | |
5530 } | |
5531 this._setMonthOnDate(pageDate, month+p); | |
5532 cal.cfg.setProperty(cfgPageDate, pageDate); | |
5533 } | |
5534 }, | |
5535 | |
5536 /** | |
5537 * Sets the calendar group's year explicitly. This year will be set into the first | |
5538 * page of the multi-page calendar, and all other months will be iterated appropriately. | |
5539 * @method setYear | |
5540 * @param {Number} year The numeric 4-digit year | |
5541 */ | |
5542 setYear : function(year) { | |
5543 | |
5544 var cfgPageDate = DEF_CFG.PAGEDATE.key; | |
5545 | |
5546 year = parseInt(year, 10); | |
5547 for (var p=0;p<this.pages.length;++p) { | |
5548 var cal = this.pages[p]; | |
5549 var pageDate = cal.cfg.getProperty(cfgPageDate); | |
5550 | |
5551 if ((pageDate.getMonth()+1) == 1 && p>0) { | |
5552 year+=1; | |
5553 } | |
5554 cal.setYear(year); | |
5555 } | |
5556 }, | |
5557 | |
5558 /** | |
5559 * Calls the render function of all child calendars within the group. | |
5560 * @method render | |
5561 */ | |
5562 render : function() { | |
5563 this.renderHeader(); | |
5564 for (var p=0;p<this.pages.length;++p) { | |
5565 var cal = this.pages[p]; | |
5566 cal.render(); | |
5567 } | |
5568 this.renderFooter(); | |
5569 }, | |
5570 | |
5571 /** | |
5572 * Selects a date or a collection of dates on the current calendar. This method, by default, | |
5573 * does not call the render method explicitly. Once selection has completed, render must be | |
5574 * called for the changes to be reflected visually. | |
5575 * @method select | |
5576 * @param {String/Date/Date[]} date The date string of dates to select in the current calendar. Valid formats are | |
5577 * individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006). | |
5578 * Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005). | |
5579 * This method can also take a JavaScript Date object or an array of Date objects. | |
5580 * @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected. | |
5581 */ | |
5582 select : function(date) { | |
5583 for (var p=0;p<this.pages.length;++p) { | |
5584 var cal = this.pages[p]; | |
5585 cal.select(date); | |
5586 } | |
5587 return this.getSelectedDates(); | |
5588 }, | |
5589 | |
5590 /** | |
5591 * 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. | |
5592 * The value of the MULTI_SELECT Configuration attribute will determine the set of dates which get selected. | |
5593 * <ul> | |
5594 * <li>If MULTI_SELECT is false, selectCell will select the cell at the specified index for only the last displayed Calendar page.</li> | |
5595 * <li>If MULTI_SELECT is true, selectCell will select the cell at the specified index, on each displayed Calendar page.</li> | |
5596 * </ul> | |
5597 * @method selectCell | |
5598 * @param {Number} cellIndex The index of the cell to be selected. | |
5599 * @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected. | |
5600 */ | |
5601 selectCell : function(cellIndex) { | |
5602 for (var p=0;p<this.pages.length;++p) { | |
5603 var cal = this.pages[p]; | |
5604 cal.selectCell(cellIndex); | |
5605 } | |
5606 return this.getSelectedDates(); | |
5607 }, | |
5608 | |
5609 /** | |
5610 * Deselects a date or a collection of dates on the current calendar. This method, by default, | |
5611 * does not call the render method explicitly. Once deselection has completed, render must be | |
5612 * called for the changes to be reflected visually. | |
5613 * @method deselect | |
5614 * @param {String/Date/Date[]} date The date string of dates to deselect in the current calendar. Valid formats are | |
5615 * individual date(s) (12/24/2005,12/26/2005) or date range(s) (12/24/2005-1/1/2006). | |
5616 * Multiple comma-delimited dates can also be passed to this method (12/24/2005,12/11/2005-12/13/2005). | |
5617 * This method can also take a JavaScript Date object or an array of Date objects. | |
5618 * @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected. | |
5619 */ | |
5620 deselect : function(date) { | |
5621 for (var p=0;p<this.pages.length;++p) { | |
5622 var cal = this.pages[p]; | |
5623 cal.deselect(date); | |
5624 } | |
5625 return this.getSelectedDates(); | |
5626 }, | |
5627 | |
5628 /** | |
5629 * Deselects all dates on the current calendar. | |
5630 * @method deselectAll | |
5631 * @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected. | |
5632 * Assuming that this function executes properly, the return value should be an empty array. | |
5633 * However, the empty array is returned for the sake of being able to check the selection status | |
5634 * of the calendar. | |
5635 */ | |
5636 deselectAll : function() { | |
5637 for (var p=0;p<this.pages.length;++p) { | |
5638 var cal = this.pages[p]; | |
5639 cal.deselectAll(); | |
5640 } | |
5641 return this.getSelectedDates(); | |
5642 }, | |
5643 | |
5644 /** | |
5645 * 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. | |
5646 * deselectCell will deselect the cell at the specified index on each displayed Calendar page. | |
5647 * | |
5648 * @method deselectCell | |
5649 * @param {Number} cellIndex The index of the cell to deselect. | |
5650 * @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected. | |
5651 */ | |
5652 deselectCell : function(cellIndex) { | |
5653 for (var p=0;p<this.pages.length;++p) { | |
5654 var cal = this.pages[p]; | |
5655 cal.deselectCell(cellIndex); | |
5656 } | |
5657 return this.getSelectedDates(); | |
5658 }, | |
5659 | |
5660 /** | |
5661 * Resets the calendar widget to the originally selected month and year, and | |
5662 * sets the calendar to the initial selection(s). | |
5663 * @method reset | |
5664 */ | |
5665 reset : function() { | |
5666 for (var p=0;p<this.pages.length;++p) { | |
5667 var cal = this.pages[p]; | |
5668 cal.reset(); | |
5669 } | |
5670 }, | |
5671 | |
5672 /** | |
5673 * Clears the selected dates in the current calendar widget and sets the calendar | |
5674 * to the current month and year. | |
5675 * @method clear | |
5676 */ | |
5677 clear : function() { | |
5678 for (var p=0;p<this.pages.length;++p) { | |
5679 var cal = this.pages[p]; | |
5680 cal.clear(); | |
5681 } | |
5682 | |
5683 this.cfg.setProperty(DEF_CFG.SELECTED.key, []); | |
5684 this.cfg.setProperty(DEF_CFG.PAGEDATE.key, new Date(this.pages[0].today.getTime())); | |
5685 this.render(); | |
5686 }, | |
5687 | |
5688 /** | |
5689 * Navigates to the next month page in the calendar widget. | |
5690 * @method nextMonth | |
5691 */ | |
5692 nextMonth : function() { | |
5693 for (var p=0;p<this.pages.length;++p) { | |
5694 var cal = this.pages[p]; | |
5695 cal.nextMonth(); | |
5696 } | |
5697 }, | |
5698 | |
5699 /** | |
5700 * Navigates to the previous month page in the calendar widget. | |
5701 * @method previousMonth | |
5702 */ | |
5703 previousMonth : function() { | |
5704 for (var p=this.pages.length-1;p>=0;--p) { | |
5705 var cal = this.pages[p]; | |
5706 cal.previousMonth(); | |
5707 } | |
5708 }, | |
5709 | |
5710 /** | |
5711 * Navigates to the next year in the currently selected month in the calendar widget. | |
5712 * @method nextYear | |
5713 */ | |
5714 nextYear : function() { | |
5715 for (var p=0;p<this.pages.length;++p) { | |
5716 var cal = this.pages[p]; | |
5717 cal.nextYear(); | |
5718 } | |
5719 }, | |
5720 | |
5721 /** | |
5722 * Navigates to the previous year in the currently selected month in the calendar widget. | |
5723 * @method previousYear | |
5724 */ | |
5725 previousYear : function() { | |
5726 for (var p=0;p<this.pages.length;++p) { | |
5727 var cal = this.pages[p]; | |
5728 cal.previousYear(); | |
5729 } | |
5730 }, | |
5731 | |
5732 /** | |
5733 * Gets the list of currently selected dates from the calendar. | |
5734 * @return An array of currently selected JavaScript Date objects. | |
5735 * @type Date[] | |
5736 */ | |
5737 getSelectedDates : function() { | |
5738 var returnDates = []; | |
5739 var selected = this.cfg.getProperty(DEF_CFG.SELECTED.key); | |
5740 for (var d=0;d<selected.length;++d) { | |
5741 var dateArray = selected[d]; | |
5742 | |
5743 var date = DateMath.getDate(dateArray[0],dateArray[1]-1,dateArray[2]); | |
5744 returnDates.push(date); | |
5745 } | |
5746 | |
5747 returnDates.sort( function(a,b) { return a-b; } ); | |
5748 return returnDates; | |
5749 }, | |
5750 | |
5751 /** | |
5752 * Adds a renderer to the render stack. The function reference passed to this method will be executed | |
5753 * when a date cell matches the conditions specified in the date string for this renderer. | |
5754 * @method addRenderer | |
5755 * @param {String} sDates A date string to associate with the specified renderer. Valid formats | |
5756 * include date (12/24/2005), month/day (12/24), and range (12/1/2004-1/1/2005) | |
5757 * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer. | |
5758 */ | |
5759 addRenderer : function(sDates, fnRender) { | |
5760 for (var p=0;p<this.pages.length;++p) { | |
5761 var cal = this.pages[p]; | |
5762 cal.addRenderer(sDates, fnRender); | |
5763 } | |
5764 }, | |
5765 | |
5766 /** | |
5767 * Adds a month to the render stack. The function reference passed to this method will be executed | |
5768 * when a date cell matches the month passed to this method. | |
5769 * @method addMonthRenderer | |
5770 * @param {Number} month The month (1-12) to associate with this renderer | |
5771 * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer. | |
5772 */ | |
5773 addMonthRenderer : function(month, fnRender) { | |
5774 for (var p=0;p<this.pages.length;++p) { | |
5775 var cal = this.pages[p]; | |
5776 cal.addMonthRenderer(month, fnRender); | |
5777 } | |
5778 }, | |
5779 | |
5780 /** | |
5781 * Adds a weekday to the render stack. The function reference passed to this method will be executed | |
5782 * when a date cell matches the weekday passed to this method. | |
5783 * @method addWeekdayRenderer | |
5784 * @param {Number} weekday The weekday (1-7) to associate with this renderer. 1=Sunday, 2=Monday etc. | |
5785 * @param {Function} fnRender The function executed to render cells that match the render rules for this renderer. | |
5786 */ | |
5787 addWeekdayRenderer : function(weekday, fnRender) { | |
5788 for (var p=0;p<this.pages.length;++p) { | |
5789 var cal = this.pages[p]; | |
5790 cal.addWeekdayRenderer(weekday, fnRender); | |
5791 } | |
5792 }, | |
5793 | |
5794 /** | |
5795 * Removes all custom renderers added to the CalendarGroup through the addRenderer, addMonthRenderer and | |
5796 * addWeekRenderer methods. CalendarGroup's render method needs to be called to after removing renderers | |
5797 * to see the changes applied. | |
5798 * | |
5799 * @method removeRenderers | |
5800 */ | |
5801 removeRenderers : function() { | |
5802 this.callChildFunction("removeRenderers"); | |
5803 }, | |
5804 | |
5805 /** | |
5806 * Renders the header for the CalendarGroup. | |
5807 * @method renderHeader | |
5808 */ | |
5809 renderHeader : function() { | |
5810 // EMPTY DEFAULT IMPL | |
5811 }, | |
5812 | |
5813 /** | |
5814 * Renders a footer for the 2-up calendar container. By default, this method is | |
5815 * unimplemented. | |
5816 * @method renderFooter | |
5817 */ | |
5818 renderFooter : function() { | |
5819 // EMPTY DEFAULT IMPL | |
5820 }, | |
5821 | |
5822 /** | |
5823 * Adds the designated number of months to the current calendar month, and sets the current | |
5824 * calendar page date to the new month. | |
5825 * @method addMonths | |
5826 * @param {Number} count The number of months to add to the current calendar | |
5827 */ | |
5828 addMonths : function(count) { | |
5829 this.callChildFunction("addMonths", count); | |
5830 }, | |
5831 | |
5832 /** | |
5833 * Subtracts the designated number of months from the current calendar month, and sets the current | |
5834 * calendar page date to the new month. | |
5835 * @method subtractMonths | |
5836 * @param {Number} count The number of months to subtract from the current calendar | |
5837 */ | |
5838 subtractMonths : function(count) { | |
5839 this.callChildFunction("subtractMonths", count); | |
5840 }, | |
5841 | |
5842 /** | |
5843 * Adds the designated number of years to the current calendar, and sets the current | |
5844 * calendar page date to the new month. | |
5845 * @method addYears | |
5846 * @param {Number} count The number of years to add to the current calendar | |
5847 */ | |
5848 addYears : function(count) { | |
5849 this.callChildFunction("addYears", count); | |
5850 }, | |
5851 | |
5852 /** | |
5853 * Subtcats the designated number of years from the current calendar, and sets the current | |
5854 * calendar page date to the new month. | |
5855 * @method subtractYears | |
5856 * @param {Number} count The number of years to subtract from the current calendar | |
5857 */ | |
5858 subtractYears : function(count) { | |
5859 this.callChildFunction("subtractYears", count); | |
5860 }, | |
5861 | |
5862 /** | |
5863 * Returns the Calendar page instance which has a pagedate (month/year) matching the given date. | |
5864 * Returns null if no match is found. | |
5865 * | |
5866 * @method getCalendarPage | |
5867 * @param {Date} date The JavaScript Date object for which a Calendar page is to be found. | |
5868 * @return {Calendar} The Calendar page instance representing the month to which the date | |
5869 * belongs. | |
5870 */ | |
5871 getCalendarPage : function(date) { | |
5872 var cal = null; | |
5873 if (date) { | |
5874 var y = date.getFullYear(), | |
5875 m = date.getMonth(); | |
5876 | |
5877 var pages = this.pages; | |
5878 for (var i = 0; i < pages.length; ++i) { | |
5879 var pageDate = pages[i].cfg.getProperty("pagedate"); | |
5880 if (pageDate.getFullYear() === y && pageDate.getMonth() === m) { | |
5881 cal = pages[i]; | |
5882 break; | |
5883 } | |
5884 } | |
5885 } | |
5886 return cal; | |
5887 }, | |
5888 | |
5889 /** | |
5890 * Sets the month on a Date object, taking into account year rollover if the month is less than 0 or greater than 11. | |
5891 * 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 | |
5892 * @method _setMonthOnDate | |
5893 * @private | |
5894 * @param {Date} date The Date object on which to set the month index | |
5895 * @param {Number} iMonth The month index to set | |
5896 */ | |
5897 _setMonthOnDate : function(date, iMonth) { | |
5898 // Bug in Safari 1.3, 2.0 (WebKit build < 420), Date.setMonth does not work consistently if iMonth is not 0-11 | |
5899 if (YAHOO.env.ua.webkit && YAHOO.env.ua.webkit < 420 && (iMonth < 0 || iMonth > 11)) { | |
5900 var newDate = DateMath.add(date, DateMath.MONTH, iMonth-date.getMonth()); | |
5901 date.setTime(newDate.getTime()); | |
5902 } else { | |
5903 date.setMonth(iMonth); | |
5904 } | |
5905 }, | |
5906 | |
5907 /** | |
5908 * Fixes the width of the CalendarGroup container element, to account for miswrapped floats | |
5909 * @method _fixWidth | |
5910 * @private | |
5911 */ | |
5912 _fixWidth : function() { | |
5913 var w = 0; | |
5914 for (var p=0;p<this.pages.length;++p) { | |
5915 var cal = this.pages[p]; | |
5916 w += cal.oDomContainer.offsetWidth; | |
5917 } | |
5918 if (w > 0) { | |
5919 this.oDomContainer.style.width = w + "px"; | |
5920 } | |
5921 }, | |
5922 | |
5923 /** | |
5924 * Returns a string representation of the object. | |
5925 * @method toString | |
5926 * @return {String} A string representation of the CalendarGroup object. | |
5927 */ | |
5928 toString : function() { | |
5929 return "CalendarGroup " + this.id; | |
5930 }, | |
5931 | |
5932 /** | |
5933 * Destroys the CalendarGroup instance. The method will remove references | |
5934 * to HTML elements, remove any event listeners added by the CalendarGroup. | |
5935 * | |
5936 * It will also destroy the Config and CalendarNavigator instances created by the | |
5937 * CalendarGroup and the individual Calendar instances created for each page. | |
5938 * | |
5939 * @method destroy | |
5940 */ | |
5941 destroy : function() { | |
5942 | |
5943 if (this.beforeDestroyEvent.fire()) { | |
5944 | |
5945 var cal = this; | |
5946 | |
5947 // Child objects | |
5948 if (cal.navigator) { | |
5949 cal.navigator.destroy(); | |
5950 } | |
5951 | |
5952 if (cal.cfg) { | |
5953 cal.cfg.destroy(); | |
5954 } | |
5955 | |
5956 // DOM event listeners | |
5957 Event.purgeElement(cal.oDomContainer, true); | |
5958 | |
5959 // Generated markup/DOM - Not removing the container DIV since we didn't create it. | |
5960 Dom.removeClass(cal.oDomContainer, CalendarGroup.CSS_CONTAINER); | |
5961 Dom.removeClass(cal.oDomContainer, CalendarGroup.CSS_MULTI_UP); | |
5962 | |
5963 for (var i = 0, l = cal.pages.length; i < l; i++) { | |
5964 cal.pages[i].destroy(); | |
5965 cal.pages[i] = null; | |
5966 } | |
5967 | |
5968 cal.oDomContainer.innerHTML = ""; | |
5969 | |
5970 // JS-to-DOM references | |
5971 cal.oDomContainer = null; | |
5972 | |
5973 this.destroyEvent.fire(); | |
5974 } | |
5975 } | |
5976 }; | |
5977 | |
5978 /** | |
5979 * CSS class representing the container for the calendar | |
5980 * @property YAHOO.widget.CalendarGroup.CSS_CONTAINER | |
5981 * @static | |
5982 * @final | |
5983 * @type String | |
5984 */ | |
5985 CalendarGroup.CSS_CONTAINER = "yui-calcontainer"; | |
5986 | |
5987 /** | |
5988 * CSS class representing the container for the calendar | |
5989 * @property YAHOO.widget.CalendarGroup.CSS_MULTI_UP | |
5990 * @static | |
5991 * @final | |
5992 * @type String | |
5993 */ | |
5994 CalendarGroup.CSS_MULTI_UP = "multi"; | |
5995 | |
5996 /** | |
5997 * CSS class representing the title for the 2-up calendar | |
5998 * @property YAHOO.widget.CalendarGroup.CSS_2UPTITLE | |
5999 * @static | |
6000 * @final | |
6001 * @type String | |
6002 */ | |
6003 CalendarGroup.CSS_2UPTITLE = "title"; | |
6004 | |
6005 /** | |
6006 * CSS class representing the close icon for the 2-up calendar | |
6007 * @property YAHOO.widget.CalendarGroup.CSS_2UPCLOSE | |
6008 * @static | |
6009 * @final | |
6010 * @deprecated Along with Calendar.IMG_ROOT and NAV_ARROW_LEFT, NAV_ARROW_RIGHT configuration properties. | |
6011 * 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 | |
6012 * @type String | |
6013 */ | |
6014 CalendarGroup.CSS_2UPCLOSE = "close-icon"; | |
6015 | |
6016 YAHOO.lang.augmentProto(CalendarGroup, Calendar, "buildDayLabel", | |
6017 "buildMonthLabel", | |
6018 "renderOutOfBoundsDate", | |
6019 "renderRowHeader", | |
6020 "renderRowFooter", | |
6021 "renderCellDefault", | |
6022 "styleCellDefault", | |
6023 "renderCellStyleHighlight1", | |
6024 "renderCellStyleHighlight2", | |
6025 "renderCellStyleHighlight3", | |
6026 "renderCellStyleHighlight4", | |
6027 "renderCellStyleToday", | |
6028 "renderCellStyleSelected", | |
6029 "renderCellNotThisMonth", | |
6030 "renderBodyCellRestricted", | |
6031 "initStyles", | |
6032 "configTitle", | |
6033 "configClose", | |
6034 "configIframe", | |
6035 "configStrings", | |
6036 "configToday", | |
6037 "configNavigator", | |
6038 "createTitleBar", | |
6039 "createCloseButton", | |
6040 "removeTitleBar", | |
6041 "removeCloseButton", | |
6042 "hide", | |
6043 "show", | |
6044 "toDate", | |
6045 "_toDate", | |
6046 "_parseArgs", | |
6047 "browser"); | |
6048 | |
6049 YAHOO.widget.CalGrp = CalendarGroup; | |
6050 YAHOO.widget.CalendarGroup = CalendarGroup; | |
6051 | |
6052 /** | |
6053 * @class YAHOO.widget.Calendar2up | |
6054 * @extends YAHOO.widget.CalendarGroup | |
6055 * @deprecated The old Calendar2up class is no longer necessary, since CalendarGroup renders in a 2up view by default. | |
6056 */ | |
6057 YAHOO.widget.Calendar2up = function(id, containerId, config) { | |
6058 this.init(id, containerId, config); | |
6059 }; | |
6060 | |
6061 YAHOO.extend(YAHOO.widget.Calendar2up, CalendarGroup); | |
6062 | |
6063 /** | |
6064 * @deprecated The old Calendar2up class is no longer necessary, since CalendarGroup renders in a 2up view by default. | |
6065 */ | |
6066 YAHOO.widget.Cal2up = YAHOO.widget.Calendar2up; | |
6067 | |
6068 })(); | |
6069 /** | |
6070 * The CalendarNavigator is used along with a Calendar/CalendarGroup to | |
6071 * provide a Month/Year popup navigation control, allowing the user to navigate | |
6072 * to a specific month/year in the Calendar/CalendarGroup without having to | |
6073 * scroll through months sequentially | |
6074 * | |
6075 * @namespace YAHOO.widget | |
6076 * @class CalendarNavigator | |
6077 * @constructor | |
6078 * @param {Calendar|CalendarGroup} cal The instance of the Calendar or CalendarGroup to which this CalendarNavigator should be attached. | |
6079 */ | |
6080 YAHOO.widget.CalendarNavigator = function(cal) { | |
6081 this.init(cal); | |
6082 }; | |
6083 | |
6084 (function() { | |
6085 // Setup static properties (inside anon fn, so that we can use shortcuts) | |
6086 var CN = YAHOO.widget.CalendarNavigator; | |
6087 | |
6088 /** | |
6089 * YAHOO.widget.CalendarNavigator.CLASSES contains constants | |
6090 * for the class values applied to the CalendarNaviatgator's | |
6091 * DOM elements | |
6092 * @property YAHOO.widget.CalendarNavigator.CLASSES | |
6093 * @type Object | |
6094 * @static | |
6095 */ | |
6096 CN.CLASSES = { | |
6097 /** | |
6098 * Class applied to the Calendar Navigator's bounding box | |
6099 * @property YAHOO.widget.CalendarNavigator.CLASSES.NAV | |
6100 * @type String | |
6101 * @static | |
6102 */ | |
6103 NAV :"yui-cal-nav", | |
6104 /** | |
6105 * Class applied to the Calendar/CalendarGroup's bounding box to indicate | |
6106 * the Navigator is currently visible | |
6107 * @property YAHOO.widget.CalendarNavigator.CLASSES.NAV_VISIBLE | |
6108 * @type String | |
6109 * @static | |
6110 */ | |
6111 NAV_VISIBLE: "yui-cal-nav-visible", | |
6112 /** | |
6113 * Class applied to the Navigator mask's bounding box | |
6114 * @property YAHOO.widget.CalendarNavigator.CLASSES.MASK | |
6115 * @type String | |
6116 * @static | |
6117 */ | |
6118 MASK : "yui-cal-nav-mask", | |
6119 /** | |
6120 * Class applied to the year label/control bounding box | |
6121 * @property YAHOO.widget.CalendarNavigator.CLASSES.YEAR | |
6122 * @type String | |
6123 * @static | |
6124 */ | |
6125 YEAR : "yui-cal-nav-y", | |
6126 /** | |
6127 * Class applied to the month label/control bounding box | |
6128 * @property YAHOO.widget.CalendarNavigator.CLASSES.MONTH | |
6129 * @type String | |
6130 * @static | |
6131 */ | |
6132 MONTH : "yui-cal-nav-m", | |
6133 /** | |
6134 * Class applied to the submit/cancel button's bounding box | |
6135 * @property YAHOO.widget.CalendarNavigator.CLASSES.BUTTONS | |
6136 * @type String | |
6137 * @static | |
6138 */ | |
6139 BUTTONS : "yui-cal-nav-b", | |
6140 /** | |
6141 * Class applied to buttons wrapping element | |
6142 * @property YAHOO.widget.CalendarNavigator.CLASSES.BUTTON | |
6143 * @type String | |
6144 * @static | |
6145 */ | |
6146 BUTTON : "yui-cal-nav-btn", | |
6147 /** | |
6148 * Class applied to the validation error area's bounding box | |
6149 * @property YAHOO.widget.CalendarNavigator.CLASSES.ERROR | |
6150 * @type String | |
6151 * @static | |
6152 */ | |
6153 ERROR : "yui-cal-nav-e", | |
6154 /** | |
6155 * Class applied to the year input control | |
6156 * @property YAHOO.widget.CalendarNavigator.CLASSES.YEAR_CTRL | |
6157 * @type String | |
6158 * @static | |
6159 */ | |
6160 YEAR_CTRL : "yui-cal-nav-yc", | |
6161 /** | |
6162 * Class applied to the month input control | |
6163 * @property YAHOO.widget.CalendarNavigator.CLASSES.MONTH_CTRL | |
6164 * @type String | |
6165 * @static | |
6166 */ | |
6167 MONTH_CTRL : "yui-cal-nav-mc", | |
6168 /** | |
6169 * Class applied to controls with invalid data (e.g. a year input field with invalid an year) | |
6170 * @property YAHOO.widget.CalendarNavigator.CLASSES.INVALID | |
6171 * @type String | |
6172 * @static | |
6173 */ | |
6174 INVALID : "yui-invalid", | |
6175 /** | |
6176 * Class applied to default controls | |
6177 * @property YAHOO.widget.CalendarNavigator.CLASSES.DEFAULT | |
6178 * @type String | |
6179 * @static | |
6180 */ | |
6181 DEFAULT : "yui-default" | |
6182 }; | |
6183 | |
6184 /** | |
6185 * Object literal containing the default configuration values for the CalendarNavigator | |
6186 * The configuration object is expected to follow the format below, with the properties being | |
6187 * case sensitive. | |
6188 * <dl> | |
6189 * <dt>strings</dt> | |
6190 * <dd><em>Object</em> : An object with the properties shown below, defining the string labels to use in the Navigator's UI | |
6191 * <dl> | |
6192 * <dt>month</dt><dd><em>String</em> : The string to use for the month label. Defaults to "Month".</dd> | |
6193 * <dt>year</dt><dd><em>String</em> : The string to use for the year label. Defaults to "Year".</dd> | |
6194 * <dt>submit</dt><dd><em>String</em> : The string to use for the submit button label. Defaults to "Okay".</dd> | |
6195 * <dt>cancel</dt><dd><em>String</em> : The string to use for the cancel button label. Defaults to "Cancel".</dd> | |
6196 * <dt>invalidYear</dt><dd><em>String</em> : The string to use for invalid year values. Defaults to "Year needs to be a number".</dd> | |
6197 * </dl> | |
6198 * </dd> | |
6199 * <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> | |
6200 * <dt>initialFocus</dt><dd><em>String</em> : Either "year" or "month" specifying which input control should get initial focus. Defaults to "year"</dd> | |
6201 * </dl> | |
6202 * @property DEFAULT_CONFIG | |
6203 * @type Object | |
6204 * @static | |
6205 */ | |
6206 CN.DEFAULT_CONFIG = { | |
6207 strings : { | |
6208 month: "Month", | |
6209 year: "Year", | |
6210 submit: "Okay", | |
6211 cancel: "Cancel", | |
6212 invalidYear : "Year needs to be a number" | |
6213 }, | |
6214 monthFormat: YAHOO.widget.Calendar.LONG, | |
6215 initialFocus: "year" | |
6216 }; | |
6217 | |
6218 /** | |
6219 * Object literal containing the default configuration values for the CalendarNavigator | |
6220 * @property _DEFAULT_CFG | |
6221 * @protected | |
6222 * @deprecated Made public. See the public DEFAULT_CONFIG property | |
6223 * @type Object | |
6224 * @static | |
6225 */ | |
6226 CN._DEFAULT_CFG = CN.DEFAULT_CONFIG; | |
6227 | |
6228 | |
6229 /** | |
6230 * The suffix added to the Calendar/CalendarGroup's ID, to generate | |
6231 * a unique ID for the Navigator and it's bounding box. | |
6232 * @property YAHOO.widget.CalendarNavigator.ID_SUFFIX | |
6233 * @static | |
6234 * @type String | |
6235 * @final | |
6236 */ | |
6237 CN.ID_SUFFIX = "_nav"; | |
6238 /** | |
6239 * The suffix added to the Navigator's ID, to generate | |
6240 * a unique ID for the month control. | |
6241 * @property YAHOO.widget.CalendarNavigator.MONTH_SUFFIX | |
6242 * @static | |
6243 * @type String | |
6244 * @final | |
6245 */ | |
6246 CN.MONTH_SUFFIX = "_month"; | |
6247 /** | |
6248 * The suffix added to the Navigator's ID, to generate | |
6249 * a unique ID for the year control. | |
6250 * @property YAHOO.widget.CalendarNavigator.YEAR_SUFFIX | |
6251 * @static | |
6252 * @type String | |
6253 * @final | |
6254 */ | |
6255 CN.YEAR_SUFFIX = "_year"; | |
6256 /** | |
6257 * The suffix added to the Navigator's ID, to generate | |
6258 * a unique ID for the error bounding box. | |
6259 * @property YAHOO.widget.CalendarNavigator.ERROR_SUFFIX | |
6260 * @static | |
6261 * @type String | |
6262 * @final | |
6263 */ | |
6264 CN.ERROR_SUFFIX = "_error"; | |
6265 /** | |
6266 * The suffix added to the Navigator's ID, to generate | |
6267 * a unique ID for the "Cancel" button. | |
6268 * @property YAHOO.widget.CalendarNavigator.CANCEL_SUFFIX | |
6269 * @static | |
6270 * @type String | |
6271 * @final | |
6272 */ | |
6273 CN.CANCEL_SUFFIX = "_cancel"; | |
6274 /** | |
6275 * The suffix added to the Navigator's ID, to generate | |
6276 * a unique ID for the "Submit" button. | |
6277 * @property YAHOO.widget.CalendarNavigator.SUBMIT_SUFFIX | |
6278 * @static | |
6279 * @type String | |
6280 * @final | |
6281 */ | |
6282 CN.SUBMIT_SUFFIX = "_submit"; | |
6283 | |
6284 /** | |
6285 * The number of digits to which the year input control is to be limited. | |
6286 * @property YAHOO.widget.CalendarNavigator.YR_MAX_DIGITS | |
6287 * @static | |
6288 * @type Number | |
6289 */ | |
6290 CN.YR_MAX_DIGITS = 4; | |
6291 | |
6292 /** | |
6293 * The amount by which to increment the current year value, | |
6294 * when the arrow up/down key is pressed on the year control | |
6295 * @property YAHOO.widget.CalendarNavigator.YR_MINOR_INC | |
6296 * @static | |
6297 * @type Number | |
6298 */ | |
6299 CN.YR_MINOR_INC = 1; | |
6300 | |
6301 /** | |
6302 * The amount by which to increment the current year value, | |
6303 * when the page up/down key is pressed on the year control | |
6304 * @property YAHOO.widget.CalendarNavigator.YR_MAJOR_INC | |
6305 * @static | |
6306 * @type Number | |
6307 */ | |
6308 CN.YR_MAJOR_INC = 10; | |
6309 | |
6310 /** | |
6311 * Artificial delay (in ms) between the time the Navigator is hidden | |
6312 * and the Calendar/CalendarGroup state is updated. Allows the user | |
6313 * the see the Calendar/CalendarGroup page changing. If set to 0 | |
6314 * the Calendar/CalendarGroup page will be updated instantly | |
6315 * @property YAHOO.widget.CalendarNavigator.UPDATE_DELAY | |
6316 * @static | |
6317 * @type Number | |
6318 */ | |
6319 CN.UPDATE_DELAY = 50; | |
6320 | |
6321 /** | |
6322 * Regular expression used to validate the year input | |
6323 * @property YAHOO.widget.CalendarNavigator.YR_PATTERN | |
6324 * @static | |
6325 * @type RegExp | |
6326 */ | |
6327 CN.YR_PATTERN = /^\d+$/; | |
6328 /** | |
6329 * Regular expression used to trim strings | |
6330 * @property YAHOO.widget.CalendarNavigator.TRIM | |
6331 * @static | |
6332 * @type RegExp | |
6333 */ | |
6334 CN.TRIM = /^\s*(.*?)\s*$/; | |
6335 })(); | |
6336 | |
6337 YAHOO.widget.CalendarNavigator.prototype = { | |
6338 | |
6339 /** | |
6340 * The unique ID for this CalendarNavigator instance | |
6341 * @property id | |
6342 * @type String | |
6343 */ | |
6344 id : null, | |
6345 | |
6346 /** | |
6347 * The Calendar/CalendarGroup instance to which the navigator belongs | |
6348 * @property cal | |
6349 * @type {Calendar|CalendarGroup} | |
6350 */ | |
6351 cal : null, | |
6352 | |
6353 /** | |
6354 * Reference to the HTMLElement used to render the navigator's bounding box | |
6355 * @property navEl | |
6356 * @type HTMLElement | |
6357 */ | |
6358 navEl : null, | |
6359 | |
6360 /** | |
6361 * Reference to the HTMLElement used to render the navigator's mask | |
6362 * @property maskEl | |
6363 * @type HTMLElement | |
6364 */ | |
6365 maskEl : null, | |
6366 | |
6367 /** | |
6368 * Reference to the HTMLElement used to input the year | |
6369 * @property yearEl | |
6370 * @type HTMLElement | |
6371 */ | |
6372 yearEl : null, | |
6373 | |
6374 /** | |
6375 * Reference to the HTMLElement used to input the month | |
6376 * @property monthEl | |
6377 * @type HTMLElement | |
6378 */ | |
6379 monthEl : null, | |
6380 | |
6381 /** | |
6382 * Reference to the HTMLElement used to display validation errors | |
6383 * @property errorEl | |
6384 * @type HTMLElement | |
6385 */ | |
6386 errorEl : null, | |
6387 | |
6388 /** | |
6389 * Reference to the HTMLElement used to update the Calendar/Calendar group | |
6390 * with the month/year values | |
6391 * @property submitEl | |
6392 * @type HTMLElement | |
6393 */ | |
6394 submitEl : null, | |
6395 | |
6396 /** | |
6397 * Reference to the HTMLElement used to hide the navigator without updating the | |
6398 * Calendar/Calendar group | |
6399 * @property cancelEl | |
6400 * @type HTMLElement | |
6401 */ | |
6402 cancelEl : null, | |
6403 | |
6404 /** | |
6405 * Reference to the first focusable control in the navigator (by default monthEl) | |
6406 * @property firstCtrl | |
6407 * @type HTMLElement | |
6408 */ | |
6409 firstCtrl : null, | |
6410 | |
6411 /** | |
6412 * Reference to the last focusable control in the navigator (by default cancelEl) | |
6413 * @property lastCtrl | |
6414 * @type HTMLElement | |
6415 */ | |
6416 lastCtrl : null, | |
6417 | |
6418 /** | |
6419 * The document containing the Calendar/Calendar group instance | |
6420 * @protected | |
6421 * @property _doc | |
6422 * @type HTMLDocument | |
6423 */ | |
6424 _doc : null, | |
6425 | |
6426 /** | |
6427 * Internal state property for the current year displayed in the navigator | |
6428 * @protected | |
6429 * @property _year | |
6430 * @type Number | |
6431 */ | |
6432 _year: null, | |
6433 | |
6434 /** | |
6435 * Internal state property for the current month index displayed in the navigator | |
6436 * @protected | |
6437 * @property _month | |
6438 * @type Number | |
6439 */ | |
6440 _month: 0, | |
6441 | |
6442 /** | |
6443 * Private internal state property which indicates whether or not the | |
6444 * Navigator has been rendered. | |
6445 * @private | |
6446 * @property __rendered | |
6447 * @type Boolean | |
6448 */ | |
6449 __rendered: false, | |
6450 | |
6451 /** | |
6452 * Init lifecycle method called as part of construction | |
6453 * | |
6454 * @method init | |
6455 * @param {Calendar} cal The instance of the Calendar or CalendarGroup to which this CalendarNavigator should be attached | |
6456 */ | |
6457 init : function(cal) { | |
6458 var calBox = cal.oDomContainer; | |
6459 | |
6460 this.cal = cal; | |
6461 this.id = calBox.id + YAHOO.widget.CalendarNavigator.ID_SUFFIX; | |
6462 this._doc = calBox.ownerDocument; | |
6463 | |
6464 /** | |
6465 * Private flag, to identify IE Quirks | |
6466 * @private | |
6467 * @property __isIEQuirks | |
6468 */ | |
6469 var ie = YAHOO.env.ua.ie; | |
6470 this.__isIEQuirks = (ie && ((ie <= 6) || (this._doc.compatMode == "BackCompat"))); | |
6471 }, | |
6472 | |
6473 /** | |
6474 * Displays the navigator and mask, updating the input controls to reflect the | |
6475 * currently set month and year. The show method will invoke the render method | |
6476 * if the navigator has not been renderered already, allowing for lazy rendering | |
6477 * of the control. | |
6478 * | |
6479 * The show method will fire the Calendar/CalendarGroup's beforeShowNav and showNav events | |
6480 * | |
6481 * @method show | |
6482 */ | |
6483 show : function() { | |
6484 var CLASSES = YAHOO.widget.CalendarNavigator.CLASSES; | |
6485 | |
6486 if (this.cal.beforeShowNavEvent.fire()) { | |
6487 if (!this.__rendered) { | |
6488 this.render(); | |
6489 } | |
6490 this.clearErrors(); | |
6491 | |
6492 this._updateMonthUI(); | |
6493 this._updateYearUI(); | |
6494 this._show(this.navEl, true); | |
6495 | |
6496 this.setInitialFocus(); | |
6497 this.showMask(); | |
6498 | |
6499 YAHOO.util.Dom.addClass(this.cal.oDomContainer, CLASSES.NAV_VISIBLE); | |
6500 this.cal.showNavEvent.fire(); | |
6501 } | |
6502 }, | |
6503 | |
6504 /** | |
6505 * Hides the navigator and mask | |
6506 * | |
6507 * The show method will fire the Calendar/CalendarGroup's beforeHideNav event and hideNav events | |
6508 * @method hide | |
6509 */ | |
6510 hide : function() { | |
6511 var CLASSES = YAHOO.widget.CalendarNavigator.CLASSES; | |
6512 | |
6513 if (this.cal.beforeHideNavEvent.fire()) { | |
6514 this._show(this.navEl, false); | |
6515 this.hideMask(); | |
6516 YAHOO.util.Dom.removeClass(this.cal.oDomContainer, CLASSES.NAV_VISIBLE); | |
6517 this.cal.hideNavEvent.fire(); | |
6518 } | |
6519 }, | |
6520 | |
6521 | |
6522 /** | |
6523 * Displays the navigator's mask element | |
6524 * | |
6525 * @method showMask | |
6526 */ | |
6527 showMask : function() { | |
6528 this._show(this.maskEl, true); | |
6529 if (this.__isIEQuirks) { | |
6530 this._syncMask(); | |
6531 } | |
6532 }, | |
6533 | |
6534 /** | |
6535 * Hides the navigator's mask element | |
6536 * | |
6537 * @method hideMask | |
6538 */ | |
6539 hideMask : function() { | |
6540 this._show(this.maskEl, false); | |
6541 }, | |
6542 | |
6543 /** | |
6544 * Returns the current month set on the navigator | |
6545 * | |
6546 * Note: This may not be the month set in the UI, if | |
6547 * the UI contains an invalid value. | |
6548 * | |
6549 * @method getMonth | |
6550 * @return {Number} The Navigator's current month index | |
6551 */ | |
6552 getMonth: function() { | |
6553 return this._month; | |
6554 }, | |
6555 | |
6556 /** | |
6557 * Returns the current year set on the navigator | |
6558 * | |
6559 * Note: This may not be the year set in the UI, if | |
6560 * the UI contains an invalid value. | |
6561 * | |
6562 * @method getYear | |
6563 * @return {Number} The Navigator's current year value | |
6564 */ | |
6565 getYear: function() { | |
6566 return this._year; | |
6567 }, | |
6568 | |
6569 /** | |
6570 * Sets the current month on the Navigator, and updates the UI | |
6571 * | |
6572 * @method setMonth | |
6573 * @param {Number} nMonth The month index, from 0 (Jan) through 11 (Dec). | |
6574 */ | |
6575 setMonth : function(nMonth) { | |
6576 if (nMonth >= 0 && nMonth < 12) { | |
6577 this._month = nMonth; | |
6578 } | |
6579 this._updateMonthUI(); | |
6580 }, | |
6581 | |
6582 /** | |
6583 * Sets the current year on the Navigator, and updates the UI. If the | |
6584 * provided year is invalid, it will not be set. | |
6585 * | |
6586 * @method setYear | |
6587 * @param {Number} nYear The full year value to set the Navigator to. | |
6588 */ | |
6589 setYear : function(nYear) { | |
6590 var yrPattern = YAHOO.widget.CalendarNavigator.YR_PATTERN; | |
6591 if (YAHOO.lang.isNumber(nYear) && yrPattern.test(nYear+"")) { | |
6592 this._year = nYear; | |
6593 } | |
6594 this._updateYearUI(); | |
6595 }, | |
6596 | |
6597 /** | |
6598 * Renders the HTML for the navigator, adding it to the | |
6599 * document and attaches event listeners if it has not | |
6600 * already been rendered. | |
6601 * | |
6602 * @method render | |
6603 */ | |
6604 render: function() { | |
6605 this.cal.beforeRenderNavEvent.fire(); | |
6606 if (!this.__rendered) { | |
6607 this.createNav(); | |
6608 this.createMask(); | |
6609 this.applyListeners(); | |
6610 this.__rendered = true; | |
6611 } | |
6612 this.cal.renderNavEvent.fire(); | |
6613 }, | |
6614 | |
6615 /** | |
6616 * Creates the navigator's containing HTMLElement, it's contents, and appends | |
6617 * the containg element to the Calendar/CalendarGroup's container. | |
6618 * | |
6619 * @method createNav | |
6620 */ | |
6621 createNav : function() { | |
6622 var NAV = YAHOO.widget.CalendarNavigator; | |
6623 var doc = this._doc; | |
6624 | |
6625 var d = doc.createElement("div"); | |
6626 d.className = NAV.CLASSES.NAV; | |
6627 | |
6628 var htmlBuf = this.renderNavContents([]); | |
6629 | |
6630 d.innerHTML = htmlBuf.join(''); | |
6631 this.cal.oDomContainer.appendChild(d); | |
6632 | |
6633 this.navEl = d; | |
6634 | |
6635 this.yearEl = doc.getElementById(this.id + NAV.YEAR_SUFFIX); | |
6636 this.monthEl = doc.getElementById(this.id + NAV.MONTH_SUFFIX); | |
6637 this.errorEl = doc.getElementById(this.id + NAV.ERROR_SUFFIX); | |
6638 this.submitEl = doc.getElementById(this.id + NAV.SUBMIT_SUFFIX); | |
6639 this.cancelEl = doc.getElementById(this.id + NAV.CANCEL_SUFFIX); | |
6640 | |
6641 if (YAHOO.env.ua.gecko && this.yearEl && this.yearEl.type == "text") { | |
6642 // Avoid XUL error on focus, select [ https://bugzilla.mozilla.org/show_bug.cgi?id=236791, | |
6643 // supposedly fixed in 1.8.1, but there are reports of it still being around for methods other than blur ] | |
6644 this.yearEl.setAttribute("autocomplete", "off"); | |
6645 } | |
6646 | |
6647 this._setFirstLastElements(); | |
6648 }, | |
6649 | |
6650 /** | |
6651 * Creates the Mask HTMLElement and appends it to the Calendar/CalendarGroups | |
6652 * container. | |
6653 * | |
6654 * @method createMask | |
6655 */ | |
6656 createMask : function() { | |
6657 var C = YAHOO.widget.CalendarNavigator.CLASSES; | |
6658 | |
6659 var d = this._doc.createElement("div"); | |
6660 d.className = C.MASK; | |
6661 | |
6662 this.cal.oDomContainer.appendChild(d); | |
6663 this.maskEl = d; | |
6664 }, | |
6665 | |
6666 /** | |
6667 * Used to set the width/height of the mask in pixels to match the Calendar Container. | |
6668 * Currently only used for IE6 or IE in quirks mode. The other A-Grade browser are handled using CSS (width/height 100%). | |
6669 * <p> | |
6670 * The method is also registered as an HTMLElement resize listener on the Calendars container element. | |
6671 * </p> | |
6672 * @protected | |
6673 * @method _syncMask | |
6674 */ | |
6675 _syncMask : function() { | |
6676 var c = this.cal.oDomContainer; | |
6677 if (c && this.maskEl) { | |
6678 var r = YAHOO.util.Dom.getRegion(c); | |
6679 YAHOO.util.Dom.setStyle(this.maskEl, "width", r.right - r.left + "px"); | |
6680 YAHOO.util.Dom.setStyle(this.maskEl, "height", r.bottom - r.top + "px"); | |
6681 } | |
6682 }, | |
6683 | |
6684 /** | |
6685 * Renders the contents of the navigator | |
6686 * | |
6687 * @method renderNavContents | |
6688 * | |
6689 * @param {Array} html The HTML buffer to append the HTML to. | |
6690 * @return {Array} A reference to the buffer passed in. | |
6691 */ | |
6692 renderNavContents : function(html) { | |
6693 var NAV = YAHOO.widget.CalendarNavigator, | |
6694 C = NAV.CLASSES, | |
6695 h = html; // just to use a shorter name | |
6696 | |
6697 h[h.length] = '<div class="' + C.MONTH + '">'; | |
6698 this.renderMonth(h); | |
6699 h[h.length] = '</div>'; | |
6700 h[h.length] = '<div class="' + C.YEAR + '">'; | |
6701 this.renderYear(h); | |
6702 h[h.length] = '</div>'; | |
6703 h[h.length] = '<div class="' + C.BUTTONS + '">'; | |
6704 this.renderButtons(h); | |
6705 h[h.length] = '</div>'; | |
6706 h[h.length] = '<div class="' + C.ERROR + '" id="' + this.id + NAV.ERROR_SUFFIX + '"></div>'; | |
6707 | |
6708 return h; | |
6709 }, | |
6710 | |
6711 /** | |
6712 * Renders the month label and control for the navigator | |
6713 * | |
6714 * @method renderNavContents | |
6715 * @param {Array} html The HTML buffer to append the HTML to. | |
6716 * @return {Array} A reference to the buffer passed in. | |
6717 */ | |
6718 renderMonth : function(html) { | |
6719 var NAV = YAHOO.widget.CalendarNavigator, | |
6720 C = NAV.CLASSES; | |
6721 | |
6722 var id = this.id + NAV.MONTH_SUFFIX, | |
6723 mf = this.__getCfg("monthFormat"), | |
6724 months = this.cal.cfg.getProperty((mf == YAHOO.widget.Calendar.SHORT) ? "MONTHS_SHORT" : "MONTHS_LONG"), | |
6725 h = html; | |
6726 | |
6727 if (months && months.length > 0) { | |
6728 h[h.length] = '<label for="' + id + '">'; | |
6729 h[h.length] = this.__getCfg("month", true); | |
6730 h[h.length] = '</label>'; | |
6731 h[h.length] = '<select name="' + id + '" id="' + id + '" class="' + C.MONTH_CTRL + '">'; | |
6732 for (var i = 0; i < months.length; i++) { | |
6733 h[h.length] = '<option value="' + i + '">'; | |
6734 h[h.length] = months[i]; | |
6735 h[h.length] = '</option>'; | |
6736 } | |
6737 h[h.length] = '</select>'; | |
6738 } | |
6739 return h; | |
6740 }, | |
6741 | |
6742 /** | |
6743 * Renders the year label and control for the navigator | |
6744 * | |
6745 * @method renderYear | |
6746 * @param {Array} html The HTML buffer to append the HTML to. | |
6747 * @return {Array} A reference to the buffer passed in. | |
6748 */ | |
6749 renderYear : function(html) { | |
6750 var NAV = YAHOO.widget.CalendarNavigator, | |
6751 C = NAV.CLASSES; | |
6752 | |
6753 var id = this.id + NAV.YEAR_SUFFIX, | |
6754 size = NAV.YR_MAX_DIGITS, | |
6755 h = html; | |
6756 | |
6757 h[h.length] = '<label for="' + id + '">'; | |
6758 h[h.length] = this.__getCfg("year", true); | |
6759 h[h.length] = '</label>'; | |
6760 h[h.length] = '<input type="text" name="' + id + '" id="' + id + '" class="' + C.YEAR_CTRL + '" maxlength="' + size + '"/>'; | |
6761 return h; | |
6762 }, | |
6763 | |
6764 /** | |
6765 * Renders the submit/cancel buttons for the navigator | |
6766 * | |
6767 * @method renderButton | |
6768 * @return {String} The HTML created for the Button UI | |
6769 */ | |
6770 renderButtons : function(html) { | |
6771 var C = YAHOO.widget.CalendarNavigator.CLASSES; | |
6772 var h = html; | |
6773 | |
6774 h[h.length] = '<span class="' + C.BUTTON + ' ' + C.DEFAULT + '">'; | |
6775 h[h.length] = '<button type="button" id="' + this.id + '_submit' + '">'; | |
6776 h[h.length] = this.__getCfg("submit", true); | |
6777 h[h.length] = '</button>'; | |
6778 h[h.length] = '</span>'; | |
6779 h[h.length] = '<span class="' + C.BUTTON +'">'; | |
6780 h[h.length] = '<button type="button" id="' + this.id + '_cancel' + '">'; | |
6781 h[h.length] = this.__getCfg("cancel", true); | |
6782 h[h.length] = '</button>'; | |
6783 h[h.length] = '</span>'; | |
6784 | |
6785 return h; | |
6786 }, | |
6787 | |
6788 /** | |
6789 * Attaches DOM event listeners to the rendered elements | |
6790 * <p> | |
6791 * The method will call applyKeyListeners, to setup keyboard specific | |
6792 * listeners | |
6793 * </p> | |
6794 * @method applyListeners | |
6795 */ | |
6796 applyListeners : function() { | |
6797 var E = YAHOO.util.Event; | |
6798 | |
6799 function yearUpdateHandler() { | |
6800 if (this.validate()) { | |
6801 this.setYear(this._getYearFromUI()); | |
6802 } | |
6803 } | |
6804 | |
6805 function monthUpdateHandler() { | |
6806 this.setMonth(this._getMonthFromUI()); | |
6807 } | |
6808 | |
6809 E.on(this.submitEl, "click", this.submit, this, true); | |
6810 E.on(this.cancelEl, "click", this.cancel, this, true); | |
6811 E.on(this.yearEl, "blur", yearUpdateHandler, this, true); | |
6812 E.on(this.monthEl, "change", monthUpdateHandler, this, true); | |
6813 | |
6814 if (this.__isIEQuirks) { | |
6815 YAHOO.util.Event.on(this.cal.oDomContainer, "resize", this._syncMask, this, true); | |
6816 } | |
6817 | |
6818 this.applyKeyListeners(); | |
6819 }, | |
6820 | |
6821 /** | |
6822 * Removes/purges DOM event listeners from the rendered elements | |
6823 * | |
6824 * @method purgeListeners | |
6825 */ | |
6826 purgeListeners : function() { | |
6827 var E = YAHOO.util.Event; | |
6828 E.removeListener(this.submitEl, "click", this.submit); | |
6829 E.removeListener(this.cancelEl, "click", this.cancel); | |
6830 E.removeListener(this.yearEl, "blur"); | |
6831 E.removeListener(this.monthEl, "change"); | |
6832 if (this.__isIEQuirks) { | |
6833 E.removeListener(this.cal.oDomContainer, "resize", this._syncMask); | |
6834 } | |
6835 | |
6836 this.purgeKeyListeners(); | |
6837 }, | |
6838 | |
6839 /** | |
6840 * Attaches DOM listeners for keyboard support. | |
6841 * Tab/Shift-Tab looping, Enter Key Submit on Year element, | |
6842 * Up/Down/PgUp/PgDown year increment on Year element | |
6843 * <p> | |
6844 * NOTE: MacOSX Safari 2.x doesn't let you tab to buttons and | |
6845 * MacOSX Gecko does not let you tab to buttons or select controls, | |
6846 * so for these browsers, Tab/Shift-Tab looping is limited to the | |
6847 * elements which can be reached using the tab key. | |
6848 * </p> | |
6849 * @method applyKeyListeners | |
6850 */ | |
6851 applyKeyListeners : function() { | |
6852 var E = YAHOO.util.Event, | |
6853 ua = YAHOO.env.ua; | |
6854 | |
6855 // IE/Safari 3.1 doesn't fire keypress for arrow/pg keys (non-char keys) | |
6856 var arrowEvt = (ua.ie || ua.webkit) ? "keydown" : "keypress"; | |
6857 | |
6858 // - IE/Safari 3.1 doesn't fire keypress for non-char keys | |
6859 // - Opera doesn't allow us to cancel keydown or keypress for tab, but | |
6860 // changes focus successfully on keydown (keypress is too late to change focus - opera's already moved on). | |
6861 var tabEvt = (ua.ie || ua.opera || ua.webkit) ? "keydown" : "keypress"; | |
6862 | |
6863 // Everyone likes keypress for Enter (char keys) - whoo hoo! | |
6864 E.on(this.yearEl, "keypress", this._handleEnterKey, this, true); | |
6865 | |
6866 E.on(this.yearEl, arrowEvt, this._handleDirectionKeys, this, true); | |
6867 E.on(this.lastCtrl, tabEvt, this._handleTabKey, this, true); | |
6868 E.on(this.firstCtrl, tabEvt, this._handleShiftTabKey, this, true); | |
6869 }, | |
6870 | |
6871 /** | |
6872 * Removes/purges DOM listeners for keyboard support | |
6873 * | |
6874 * @method purgeKeyListeners | |
6875 */ | |
6876 purgeKeyListeners : function() { | |
6877 var E = YAHOO.util.Event, | |
6878 ua = YAHOO.env.ua; | |
6879 | |
6880 var arrowEvt = (ua.ie || ua.webkit) ? "keydown" : "keypress"; | |
6881 var tabEvt = (ua.ie || ua.opera || ua.webkit) ? "keydown" : "keypress"; | |
6882 | |
6883 E.removeListener(this.yearEl, "keypress", this._handleEnterKey); | |
6884 E.removeListener(this.yearEl, arrowEvt, this._handleDirectionKeys); | |
6885 E.removeListener(this.lastCtrl, tabEvt, this._handleTabKey); | |
6886 E.removeListener(this.firstCtrl, tabEvt, this._handleShiftTabKey); | |
6887 }, | |
6888 | |
6889 /** | |
6890 * Updates the Calendar/CalendarGroup's pagedate with the currently set month and year if valid. | |
6891 * <p> | |
6892 * If the currently set month/year is invalid, a validation error will be displayed and the | |
6893 * Calendar/CalendarGroup's pagedate will not be updated. | |
6894 * </p> | |
6895 * @method submit | |
6896 */ | |
6897 submit : function() { | |
6898 if (this.validate()) { | |
6899 this.hide(); | |
6900 | |
6901 this.setMonth(this._getMonthFromUI()); | |
6902 this.setYear(this._getYearFromUI()); | |
6903 | |
6904 var cal = this.cal; | |
6905 | |
6906 // Artificial delay, just to help the user see something changed | |
6907 var delay = YAHOO.widget.CalendarNavigator.UPDATE_DELAY; | |
6908 if (delay > 0) { | |
6909 var nav = this; | |
6910 window.setTimeout(function(){ nav._update(cal); }, delay); | |
6911 } else { | |
6912 this._update(cal); | |
6913 } | |
6914 } | |
6915 }, | |
6916 | |
6917 /** | |
6918 * Updates the Calendar rendered state, based on the state of the CalendarNavigator | |
6919 * @method _update | |
6920 * @param cal The Calendar instance to update | |
6921 * @protected | |
6922 */ | |
6923 _update : function(cal) { | |
6924 var date = YAHOO.widget.DateMath.getDate(this.getYear() - cal.cfg.getProperty("YEAR_OFFSET"), this.getMonth(), 1); | |
6925 cal.cfg.setProperty("pagedate", date); | |
6926 cal.render(); | |
6927 }, | |
6928 | |
6929 /** | |
6930 * Hides the navigator and mask, without updating the Calendar/CalendarGroup's state | |
6931 * | |
6932 * @method cancel | |
6933 */ | |
6934 cancel : function() { | |
6935 this.hide(); | |
6936 }, | |
6937 | |
6938 /** | |
6939 * Validates the current state of the UI controls | |
6940 * | |
6941 * @method validate | |
6942 * @return {Boolean} true, if the current UI state contains valid values, false if not | |
6943 */ | |
6944 validate : function() { | |
6945 if (this._getYearFromUI() !== null) { | |
6946 this.clearErrors(); | |
6947 return true; | |
6948 } else { | |
6949 this.setYearError(); | |
6950 this.setError(this.__getCfg("invalidYear", true)); | |
6951 return false; | |
6952 } | |
6953 }, | |
6954 | |
6955 /** | |
6956 * Displays an error message in the Navigator's error panel | |
6957 * @method setError | |
6958 * @param {String} msg The error message to display | |
6959 */ | |
6960 setError : function(msg) { | |
6961 if (this.errorEl) { | |
6962 this.errorEl.innerHTML = msg; | |
6963 this._show(this.errorEl, true); | |
6964 } | |
6965 }, | |
6966 | |
6967 /** | |
6968 * Clears the navigator's error message and hides the error panel | |
6969 * @method clearError | |
6970 */ | |
6971 clearError : function() { | |
6972 if (this.errorEl) { | |
6973 this.errorEl.innerHTML = ""; | |
6974 this._show(this.errorEl, false); | |
6975 } | |
6976 }, | |
6977 | |
6978 /** | |
6979 * Displays the validation error UI for the year control | |
6980 * @method setYearError | |
6981 */ | |
6982 setYearError : function() { | |
6983 YAHOO.util.Dom.addClass(this.yearEl, YAHOO.widget.CalendarNavigator.CLASSES.INVALID); | |
6984 }, | |
6985 | |
6986 /** | |
6987 * Removes the validation error UI for the year control | |
6988 * @method clearYearError | |
6989 */ | |
6990 clearYearError : function() { | |
6991 YAHOO.util.Dom.removeClass(this.yearEl, YAHOO.widget.CalendarNavigator.CLASSES.INVALID); | |
6992 }, | |
6993 | |
6994 /** | |
6995 * Clears all validation and error messages in the UI | |
6996 * @method clearErrors | |
6997 */ | |
6998 clearErrors : function() { | |
6999 this.clearError(); | |
7000 this.clearYearError(); | |
7001 }, | |
7002 | |
7003 /** | |
7004 * Sets the initial focus, based on the configured value | |
7005 * @method setInitialFocus | |
7006 */ | |
7007 setInitialFocus : function() { | |
7008 var el = this.submitEl, | |
7009 f = this.__getCfg("initialFocus"); | |
7010 | |
7011 if (f && f.toLowerCase) { | |
7012 f = f.toLowerCase(); | |
7013 if (f == "year") { | |
7014 el = this.yearEl; | |
7015 try { | |
7016 this.yearEl.select(); | |
7017 } catch (selErr) { | |
7018 // Ignore; | |
7019 } | |
7020 } else if (f == "month") { | |
7021 el = this.monthEl; | |
7022 } | |
7023 } | |
7024 | |
7025 if (el && YAHOO.lang.isFunction(el.focus)) { | |
7026 try { | |
7027 el.focus(); | |
7028 } catch (focusErr) { | |
7029 // TODO: Fall back if focus fails? | |
7030 } | |
7031 } | |
7032 }, | |
7033 | |
7034 /** | |
7035 * Removes all renderered HTML elements for the Navigator from | |
7036 * the DOM, purges event listeners and clears (nulls) any property | |
7037 * references to HTML references | |
7038 * @method erase | |
7039 */ | |
7040 erase : function() { | |
7041 if (this.__rendered) { | |
7042 this.purgeListeners(); | |
7043 | |
7044 // Clear out innerHTML references | |
7045 this.yearEl = null; | |
7046 this.monthEl = null; | |
7047 this.errorEl = null; | |
7048 this.submitEl = null; | |
7049 this.cancelEl = null; | |
7050 this.firstCtrl = null; | |
7051 this.lastCtrl = null; | |
7052 if (this.navEl) { | |
7053 this.navEl.innerHTML = ""; | |
7054 } | |
7055 | |
7056 var p = this.navEl.parentNode; | |
7057 if (p) { | |
7058 p.removeChild(this.navEl); | |
7059 } | |
7060 this.navEl = null; | |
7061 | |
7062 var pm = this.maskEl.parentNode; | |
7063 if (pm) { | |
7064 pm.removeChild(this.maskEl); | |
7065 } | |
7066 this.maskEl = null; | |
7067 this.__rendered = false; | |
7068 } | |
7069 }, | |
7070 | |
7071 /** | |
7072 * Destroys the Navigator object and any HTML references | |
7073 * @method destroy | |
7074 */ | |
7075 destroy : function() { | |
7076 this.erase(); | |
7077 this._doc = null; | |
7078 this.cal = null; | |
7079 this.id = null; | |
7080 }, | |
7081 | |
7082 /** | |
7083 * Protected implementation to handle how UI elements are | |
7084 * hidden/shown. | |
7085 * | |
7086 * @method _show | |
7087 * @protected | |
7088 */ | |
7089 _show : function(el, bShow) { | |
7090 if (el) { | |
7091 YAHOO.util.Dom.setStyle(el, "display", (bShow) ? "block" : "none"); | |
7092 } | |
7093 }, | |
7094 | |
7095 /** | |
7096 * Returns the month value (index), from the month UI element | |
7097 * @protected | |
7098 * @method _getMonthFromUI | |
7099 * @return {Number} The month index, or 0 if a UI element for the month | |
7100 * is not found | |
7101 */ | |
7102 _getMonthFromUI : function() { | |
7103 if (this.monthEl) { | |
7104 return this.monthEl.selectedIndex; | |
7105 } else { | |
7106 return 0; // Default to Jan | |
7107 } | |
7108 }, | |
7109 | |
7110 /** | |
7111 * Returns the year value, from the Navitator's year UI element | |
7112 * @protected | |
7113 * @method _getYearFromUI | |
7114 * @return {Number} The year value set in the UI, if valid. null is returned if | |
7115 * the UI does not contain a valid year value. | |
7116 */ | |
7117 _getYearFromUI : function() { | |
7118 var NAV = YAHOO.widget.CalendarNavigator; | |
7119 | |
7120 var yr = null; | |
7121 if (this.yearEl) { | |
7122 var value = this.yearEl.value; | |
7123 value = value.replace(NAV.TRIM, "$1"); | |
7124 | |
7125 if (NAV.YR_PATTERN.test(value)) { | |
7126 yr = parseInt(value, 10); | |
7127 } | |
7128 } | |
7129 return yr; | |
7130 }, | |
7131 | |
7132 /** | |
7133 * Updates the Navigator's year UI, based on the year value set on the Navigator object | |
7134 * @protected | |
7135 * @method _updateYearUI | |
7136 */ | |
7137 _updateYearUI : function() { | |
7138 if (this.yearEl && this._year !== null) { | |
7139 this.yearEl.value = this._year; | |
7140 } | |
7141 }, | |
7142 | |
7143 /** | |
7144 * Updates the Navigator's month UI, based on the month value set on the Navigator object | |
7145 * @protected | |
7146 * @method _updateMonthUI | |
7147 */ | |
7148 _updateMonthUI : function() { | |
7149 if (this.monthEl) { | |
7150 this.monthEl.selectedIndex = this._month; | |
7151 } | |
7152 }, | |
7153 | |
7154 /** | |
7155 * Sets up references to the first and last focusable element in the Navigator's UI | |
7156 * in terms of tab order (Naviagator's firstEl and lastEl properties). The references | |
7157 * are used to control modality by looping around from the first to the last control | |
7158 * and visa versa for tab/shift-tab navigation. | |
7159 * <p> | |
7160 * See <a href="#applyKeyListeners">applyKeyListeners</a> | |
7161 * </p> | |
7162 * @protected | |
7163 * @method _setFirstLastElements | |
7164 */ | |
7165 _setFirstLastElements : function() { | |
7166 this.firstCtrl = this.monthEl; | |
7167 this.lastCtrl = this.cancelEl; | |
7168 | |
7169 // Special handling for MacOSX. | |
7170 // - Safari 2.x can't focus on buttons | |
7171 // - Gecko can't focus on select boxes or buttons | |
7172 if (this.__isMac) { | |
7173 if (YAHOO.env.ua.webkit && YAHOO.env.ua.webkit < 420){ | |
7174 this.firstCtrl = this.monthEl; | |
7175 this.lastCtrl = this.yearEl; | |
7176 } | |
7177 if (YAHOO.env.ua.gecko) { | |
7178 this.firstCtrl = this.yearEl; | |
7179 this.lastCtrl = this.yearEl; | |
7180 } | |
7181 } | |
7182 }, | |
7183 | |
7184 /** | |
7185 * Default Keyboard event handler to capture Enter | |
7186 * on the Navigator's year control (yearEl) | |
7187 * | |
7188 * @method _handleEnterKey | |
7189 * @protected | |
7190 * @param {Event} e The DOM event being handled | |
7191 */ | |
7192 _handleEnterKey : function(e) { | |
7193 var KEYS = YAHOO.util.KeyListener.KEY; | |
7194 | |
7195 if (YAHOO.util.Event.getCharCode(e) == KEYS.ENTER) { | |
7196 YAHOO.util.Event.preventDefault(e); | |
7197 this.submit(); | |
7198 } | |
7199 }, | |
7200 | |
7201 /** | |
7202 * Default Keyboard event handler to capture up/down/pgup/pgdown | |
7203 * on the Navigator's year control (yearEl). | |
7204 * | |
7205 * @method _handleDirectionKeys | |
7206 * @protected | |
7207 * @param {Event} e The DOM event being handled | |
7208 */ | |
7209 _handleDirectionKeys : function(e) { | |
7210 var E = YAHOO.util.Event, | |
7211 KEYS = YAHOO.util.KeyListener.KEY, | |
7212 NAV = YAHOO.widget.CalendarNavigator; | |
7213 | |
7214 var value = (this.yearEl.value) ? parseInt(this.yearEl.value, 10) : null; | |
7215 if (isFinite(value)) { | |
7216 var dir = false; | |
7217 switch(E.getCharCode(e)) { | |
7218 case KEYS.UP: | |
7219 this.yearEl.value = value + NAV.YR_MINOR_INC; | |
7220 dir = true; | |
7221 break; | |
7222 case KEYS.DOWN: | |
7223 this.yearEl.value = Math.max(value - NAV.YR_MINOR_INC, 0); | |
7224 dir = true; | |
7225 break; | |
7226 case KEYS.PAGE_UP: | |
7227 this.yearEl.value = value + NAV.YR_MAJOR_INC; | |
7228 dir = true; | |
7229 break; | |
7230 case KEYS.PAGE_DOWN: | |
7231 this.yearEl.value = Math.max(value - NAV.YR_MAJOR_INC, 0); | |
7232 dir = true; | |
7233 break; | |
7234 default: | |
7235 break; | |
7236 } | |
7237 if (dir) { | |
7238 E.preventDefault(e); | |
7239 try { | |
7240 this.yearEl.select(); | |
7241 } catch(err) { | |
7242 // Ignore | |
7243 } | |
7244 } | |
7245 } | |
7246 }, | |
7247 | |
7248 /** | |
7249 * Default Keyboard event handler to capture Tab | |
7250 * on the last control (lastCtrl) in the Navigator. | |
7251 * | |
7252 * @method _handleTabKey | |
7253 * @protected | |
7254 * @param {Event} e The DOM event being handled | |
7255 */ | |
7256 _handleTabKey : function(e) { | |
7257 var E = YAHOO.util.Event, | |
7258 KEYS = YAHOO.util.KeyListener.KEY; | |
7259 | |
7260 if (E.getCharCode(e) == KEYS.TAB && !e.shiftKey) { | |
7261 try { | |
7262 E.preventDefault(e); | |
7263 this.firstCtrl.focus(); | |
7264 } catch (err) { | |
7265 // Ignore - mainly for focus edge cases | |
7266 } | |
7267 } | |
7268 }, | |
7269 | |
7270 /** | |
7271 * Default Keyboard event handler to capture Shift-Tab | |
7272 * on the first control (firstCtrl) in the Navigator. | |
7273 * | |
7274 * @method _handleShiftTabKey | |
7275 * @protected | |
7276 * @param {Event} e The DOM event being handled | |
7277 */ | |
7278 _handleShiftTabKey : function(e) { | |
7279 var E = YAHOO.util.Event, | |
7280 KEYS = YAHOO.util.KeyListener.KEY; | |
7281 | |
7282 if (e.shiftKey && E.getCharCode(e) == KEYS.TAB) { | |
7283 try { | |
7284 E.preventDefault(e); | |
7285 this.lastCtrl.focus(); | |
7286 } catch (err) { | |
7287 // Ignore - mainly for focus edge cases | |
7288 } | |
7289 } | |
7290 }, | |
7291 | |
7292 /** | |
7293 * Retrieve Navigator configuration values from | |
7294 * the parent Calendar/CalendarGroup's config value. | |
7295 * <p> | |
7296 * If it has not been set in the user provided configuration, the method will | |
7297 * return the default value of the configuration property, as set in DEFAULT_CONFIG | |
7298 * </p> | |
7299 * @private | |
7300 * @method __getCfg | |
7301 * @param {String} Case sensitive property name. | |
7302 * @param {Boolean} true, if the property is a string property, false if not. | |
7303 * @return The value of the configuration property | |
7304 */ | |
7305 __getCfg : function(prop, bIsStr) { | |
7306 var DEF_CFG = YAHOO.widget.CalendarNavigator.DEFAULT_CONFIG; | |
7307 var cfg = this.cal.cfg.getProperty("navigator"); | |
7308 | |
7309 if (bIsStr) { | |
7310 return (cfg !== true && cfg.strings && cfg.strings[prop]) ? cfg.strings[prop] : DEF_CFG.strings[prop]; | |
7311 } else { | |
7312 return (cfg !== true && cfg[prop]) ? cfg[prop] : DEF_CFG[prop]; | |
7313 } | |
7314 }, | |
7315 | |
7316 /** | |
7317 * Private flag, to identify MacOS | |
7318 * @private | |
7319 * @property __isMac | |
7320 */ | |
7321 __isMac : (navigator.userAgent.toLowerCase().indexOf("macintosh") != -1) | |
7322 | |
7323 }; | |
1073
289ff43cc190
update YUI dev libs to latest version
Marcin Kuzminski <marcin@python-works.com>
parents:
547
diff
changeset
|
7324 YAHOO.register("calendar", YAHOO.widget.Calendar, {version: "2.8.2r1", build: "7"}); |