MDL-9137 Fixing errors in the overview report
[moodle-pu.git] / lib / yui / container / container_core-debug.js
blobefb6676b52ef8e4854bce2384c0a0aae82cc71a8
1 /*
2 Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 2.3.0
6 */
7 (function () {
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     
24             this.init(owner);
25     
26         }
27     
28         if (!owner) { 
29         
30             YAHOO.log("No owner specified for Config object", "error"); 
31     
32         }
33     
34     };
37     var Lang = YAHOO.lang,
38         CustomEvent = YAHOO.util.CustomEvent,        
39         Config = YAHOO.util.Config;
40     
42     /**
43      * Constant representing the CustomEvent type for the config changed event.
44      * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
45      * @private
46      * @static
47      * @final
48      */
49     Config.CONFIG_CHANGED_EVENT = "configChanged";
50     
51     /**
52      * Constant representing the boolean type string
53      * @property YAHOO.util.Config.BOOLEAN_TYPE
54      * @private
55      * @static
56      * @final
57      */
58     Config.BOOLEAN_TYPE = "boolean";
59     
60     Config.prototype = {
61      
62         /**
63         * Object reference to the owner of this Config Object
64         * @property owner
65         * @type Object
66         */
67         owner: null,
68         
69         /**
70         * Boolean flag that specifies whether a queue is currently 
71         * being executed
72         * @property queueInProgress
73         * @type Boolean
74         */
75         queueInProgress: false,
76         
77         /**
78         * Maintains the local collection of configuration property objects and 
79         * their specified values
80         * @property config
81         * @private
82         * @type Object
83         */ 
84         config: null,
85         
86         /**
87         * Maintains the local collection of configuration property objects as 
88         * they were initially applied.
89         * This object is used when resetting a property.
90         * @property initialConfig
91         * @private
92         * @type Object
93         */ 
94         initialConfig: null,
95         
96         /**
97         * Maintains the local, normalized CustomEvent queue
98         * @property eventQueue
99         * @private
100         * @type Object
101         */ 
102         eventQueue: null,
103         
104         /**
105         * Custom Event, notifying subscribers when Config properties are set 
106         * (setProperty is called without the silent flag
107         * @event configChangedEvent
108         */
109         configChangedEvent: null,
110     
111         /**
112         * Initializes the configuration Object and all of its local members.
113         * @method init
114         * @param {Object} owner The owner Object to which this Config 
115         * Object belongs
116         */
117         init: function (owner) {
118     
119             this.owner = owner;
120     
121             this.configChangedEvent = 
122                 this.createEvent(Config.CONFIG_CHANGED_EVENT);
123     
124             this.configChangedEvent.signature = CustomEvent.LIST;
125             this.queueInProgress = false;
126             this.config = {};
127             this.initialConfig = {};
128             this.eventQueue = [];
129         
130         },
131         
132         /**
133         * Validates that the value passed in is a Boolean.
134         * @method checkBoolean
135         * @param {Object} val The value to validate
136         * @return {Boolean} true, if the value is valid
137         */ 
138         checkBoolean: function (val) {
139             return (typeof val == Config.BOOLEAN_TYPE);
140         },
141         
142         /**
143         * Validates that the value passed in is a number.
144         * @method checkNumber
145         * @param {Object} val The value to validate
146         * @return {Boolean} true, if the value is valid
147         */
148         checkNumber: function (val) {
149             return (!isNaN(val));
150         },
151         
152         /**
153         * Fires a configuration property event using the specified value. 
154         * @method fireEvent
155         * @private
156         * @param {String} key The configuration property's name
157         * @param {value} Object The value of the correct type for the property
158         */ 
159         fireEvent: function ( key, value ) {
160             YAHOO.log("Firing Config event: " + key + "=" + value, "info");
161             var property = this.config[key];
162         
163             if (property && property.event) {
164                 property.event.fire(value);
165             } 
166         },
167         
168         /**
169         * Adds a property to the Config Object's private config hash.
170         * @method addProperty
171         * @param {String} key The configuration property's name
172         * @param {Object} propertyObject The Object containing all of this 
173         * property's arguments
174         */
175         addProperty: function ( key, propertyObject ) {
176             key = key.toLowerCase();
177             YAHOO.log("Added property: " + key, "info");
178         
179             this.config[key] = propertyObject;
180         
181             propertyObject.event = this.createEvent(key, { scope: this.owner });
182             propertyObject.event.signature = CustomEvent.LIST;
183             
184             
185             propertyObject.key = key;
186         
187             if (propertyObject.handler) {
188                 propertyObject.event.subscribe(propertyObject.handler, 
189                     this.owner);
190             }
191         
192             this.setProperty(key, propertyObject.value, true);
193             
194             if (! propertyObject.suppressEvent) {
195                 this.queueProperty(key, propertyObject.value);
196             }
197             
198         },
199         
200         /**
201         * Returns a key-value configuration map of the values currently set in  
202         * the Config Object.
203         * @method getConfig
204         * @return {Object} The current config, represented in a key-value map
205         */
206         getConfig: function () {
207         
208             var cfg = {},
209                 prop,
210                 property;
211                 
212             for (prop in this.config) {
213                 property = this.config[prop];
214                 if (property && property.event) {
215                     cfg[prop] = property.value;
216                 }
217             }
218             
219             return cfg;
220         },
221         
222         /**
223         * Returns the value of specified property.
224         * @method getProperty
225         * @param {String} key The name of the property
226         * @return {Object}  The value of the specified property
227         */
228         getProperty: function (key) {
229             var property = this.config[key.toLowerCase()];
230             if (property && property.event) {
231                 return property.value;
232             } else {
233                 return undefined;
234             }
235         },
236         
237         /**
238         * Resets the specified property's value to its initial value.
239         * @method resetProperty
240         * @param {String} key The name of the property
241         * @return {Boolean} True is the property was reset, false if not
242         */
243         resetProperty: function (key) {
244     
245             key = key.toLowerCase();
246         
247             var property = this.config[key];
248     
249             if (property && property.event) {
250     
251                 if (this.initialConfig[key] && 
252                     !Lang.isUndefined(this.initialConfig[key])) {
253     
254                     this.setProperty(key, this.initialConfig[key]);
256                     return true;
257     
258                 }
259     
260             } else {
261     
262                 return false;
263             }
264     
265         },
266         
267         /**
268         * Sets the value of a property. If the silent property is passed as 
269         * true, the property's event will not be fired.
270         * @method setProperty
271         * @param {String} key The name of the property
272         * @param {String} value The value to set the property to
273         * @param {Boolean} silent Whether the value should be set silently, 
274         * without firing the property event.
275         * @return {Boolean} True, if the set was successful, false if it failed.
276         */
277         setProperty: function (key, value, silent) {
278         
279             var property;
280         
281             key = key.toLowerCase();
282             YAHOO.log("setProperty: " + key + "=" + value, "info");
283         
284             if (this.queueInProgress && ! silent) {
285                 // Currently running through a queue... 
286                 this.queueProperty(key,value);
287                 return true;
288     
289             } else {
290                 property = this.config[key];
291                 if (property && property.event) {
292                     if (property.validator && !property.validator(value)) {
293                         return false;
294                     } else {
295                         property.value = value;
296                         if (! silent) {
297                             this.fireEvent(key, value);
298                             this.configChangedEvent.fire([key, value]);
299                         }
300                         return true;
301                     }
302                 } else {
303                     return false;
304                 }
305             }
306         },
307         
308         /**
309         * Sets the value of a property and queues its event to execute. If the 
310         * event is already scheduled to execute, it is
311         * moved from its current position to the end of the queue.
312         * @method queueProperty
313         * @param {String} key The name of the property
314         * @param {String} value The value to set the property to
315         * @return {Boolean}  true, if the set was successful, false if 
316         * it failed.
317         */ 
318         queueProperty: function (key, value) {
319         
320             key = key.toLowerCase();
321             YAHOO.log("queueProperty: " + key + "=" + value, "info");
322         
323             var property = this.config[key],
324                 foundDuplicate = false,
325                 iLen,
326                 queueItem,
327                 queueItemKey,
328                 queueItemValue,
329                 sLen,
330                 supercedesCheck,
331                 qLen,
332                 queueItemCheck,
333                 queueItemCheckKey,
334                 queueItemCheckValue,
335                 i,
336                 s,
337                 q;
338                                 
339             if (property && property.event) {
340     
341                 if (!Lang.isUndefined(value) && property.validator && 
342                     !property.validator(value)) { // validator
343                     return false;
344                 } else {
345         
346                     if (!Lang.isUndefined(value)) {
347                         property.value = value;
348                     } else {
349                         value = property.value;
350                     }
351         
352                     foundDuplicate = false;
353                     iLen = this.eventQueue.length;
354         
355                     for (i = 0; i < iLen; i++) {
356                         queueItem = this.eventQueue[i];
357         
358                         if (queueItem) {
359                             queueItemKey = queueItem[0];
360                             queueItemValue = queueItem[1];
361                             
362                             if (queueItemKey == key) {
363     
364                                 /*
365                                     found a dupe... push to end of queue, null 
366                                     current item, and break
367                                 */
368     
369                                 this.eventQueue[i] = null;
370     
371                                 this.eventQueue.push(
372                                     [key, (!Lang.isUndefined(value) ? 
373                                     value : queueItemValue)]);
374     
375                                 foundDuplicate = true;
376                                 break;
377                             }
378                         }
379                     }
380                     
381                     // this is a refire, or a new property in the queue
382     
383                     if (! foundDuplicate && !Lang.isUndefined(value)) { 
384                         this.eventQueue.push([key, value]);
385                     }
386                 }
387         
388                 if (property.supercedes) {
389         
390                     sLen = property.supercedes.length;
391         
392                     for (s = 0; s < sLen; s++) {
393         
394                         supercedesCheck = property.supercedes[s];
395                         qLen = this.eventQueue.length;
396         
397                         for (q = 0; q < qLen; q++) {
398                             queueItemCheck = this.eventQueue[q];
399         
400                             if (queueItemCheck) {
401                                 queueItemCheckKey = queueItemCheck[0];
402                                 queueItemCheckValue = queueItemCheck[1];
403                                 
404                                 if (queueItemCheckKey == 
405                                     supercedesCheck.toLowerCase() ) {
406     
407                                     this.eventQueue.push([queueItemCheckKey, 
408                                         queueItemCheckValue]);
409     
410                                     this.eventQueue[q] = null;
411                                     break;
412     
413                                 }
414                             }
415                         }
416                     }
417                 }
419                 YAHOO.log("Config event queue: " + this.outputEventQueue(), "info");
420         
421                 return true;
422             } else {
423                 return false;
424             }
425         },
426         
427         /**
428         * Fires the event for a property using the property's current value.
429         * @method refireEvent
430         * @param {String} key The name of the property
431         */
432         refireEvent: function (key) {
433     
434             key = key.toLowerCase();
435         
436             var property = this.config[key];
437     
438             if (property && property.event && 
439     
440                 !Lang.isUndefined(property.value)) {
441     
442                 if (this.queueInProgress) {
443     
444                     this.queueProperty(key);
445     
446                 } else {
447     
448                     this.fireEvent(key, property.value);
449     
450                 }
451     
452             }
453         },
454         
455         /**
456         * Applies a key-value Object literal to the configuration, replacing  
457         * any existing values, and queueing the property events.
458         * Although the values will be set, fireQueue() must be called for their 
459         * associated events to execute.
460         * @method applyConfig
461         * @param {Object} userConfig The configuration Object literal
462         * @param {Boolean} init  When set to true, the initialConfig will 
463         * be set to the userConfig passed in, so that calling a reset will 
464         * reset the properties to the passed values.
465         */
466         applyConfig: function (userConfig, init) {
467         
468             var sKey,
469                 oValue,
470                 oConfig;
472             if (init) {
474                 oConfig = {};
476                 for (sKey in userConfig) {
477                 
478                     if (Lang.hasOwnProperty(userConfig, sKey)) {
480                         oConfig[sKey.toLowerCase()] = userConfig[sKey];
482                     }
483                 
484                 }
486                 this.initialConfig = oConfig;
488             }
490             for (sKey in userConfig) {
491             
492                 if (Lang.hasOwnProperty(userConfig, sKey)) {
493             
494                     this.queueProperty(sKey, userConfig[sKey]);
495                 
496                 }
498             }
500         },
501         
502         /**
503         * Refires the events for all configuration properties using their 
504         * current values.
505         * @method refresh
506         */
507         refresh: function () {
508         
509             var prop;
510         
511             for (prop in this.config) {
512                 this.refireEvent(prop);
513             }
514         },
515         
516         /**
517         * Fires the normalized list of queued property change events
518         * @method fireQueue
519         */
520         fireQueue: function () {
521         
522             var i, 
523                 queueItem,
524                 key,
525                 value,
526                 property;
527         
528             this.queueInProgress = true;
529             for (i = 0;i < this.eventQueue.length; i++) {
530                 queueItem = this.eventQueue[i];
531                 if (queueItem) {
532         
533                     key = queueItem[0];
534                     value = queueItem[1];
535                     property = this.config[key];
536         
537                     property.value = value;
538         
539                     this.fireEvent(key,value);
540                 }
541             }
542             
543             this.queueInProgress = false;
544             this.eventQueue = [];
545         },
546         
547         /**
548         * Subscribes an external handler to the change event for any 
549         * given property. 
550         * @method subscribeToConfigEvent
551         * @param {String} key The property name
552         * @param {Function} handler The handler function to use subscribe to 
553         * the property's event
554         * @param {Object} obj The Object to use for scoping the event handler 
555         * (see CustomEvent documentation)
556         * @param {Boolean} override Optional. If true, will override "this"  
557         * within the handler to map to the scope Object passed into the method.
558         * @return {Boolean} True, if the subscription was successful, 
559         * otherwise false.
560         */ 
561         subscribeToConfigEvent: function (key, handler, obj, override) {
562     
563             var property = this.config[key.toLowerCase()];
564     
565             if (property && property.event) {
566     
567                 if (!Config.alreadySubscribed(property.event, handler, obj)) {
568     
569                     property.event.subscribe(handler, obj, override);
570     
571                 }
572     
573                 return true;
574     
575             } else {
576     
577                 return false;
578     
579             }
580     
581         },
582         
583         /**
584         * Unsubscribes an external handler from the change event for any 
585         * given property. 
586         * @method unsubscribeFromConfigEvent
587         * @param {String} key The property name
588         * @param {Function} handler The handler function to use subscribe to 
589         * the property's event
590         * @param {Object} obj The Object to use for scoping the event 
591         * handler (see CustomEvent documentation)
592         * @return {Boolean} True, if the unsubscription was successful, 
593         * otherwise false.
594         */
595         unsubscribeFromConfigEvent: function (key, handler, obj) {
596             var property = this.config[key.toLowerCase()];
597             if (property && property.event) {
598                 return property.event.unsubscribe(handler, obj);
599             } else {
600                 return false;
601             }
602         },
603         
604         /**
605         * Returns a string representation of the Config object
606         * @method toString
607         * @return {String} The Config object in string format.
608         */
609         toString: function () {
610             var output = "Config";
611             if (this.owner) {
612                 output += " [" + this.owner.toString() + "]";
613             }
614             return output;
615         },
616         
617         /**
618         * Returns a string representation of the Config object's current 
619         * CustomEvent queue
620         * @method outputEventQueue
621         * @return {String} The string list of CustomEvents currently queued 
622         * for execution
623         */
624         outputEventQueue: function () {
626             var output = "",
627                 queueItem,
628                 q,
629                 nQueue = this.eventQueue.length;
630               
631             for (q = 0; q < nQueue; q++) {
632                 queueItem = this.eventQueue[q];
633                 if (queueItem) {
634                     output += queueItem[0] + "=" + queueItem[1] + ", ";
635                 }
636             }
637             return output;
638         },
640         /**
641         * Sets all properties to null, unsubscribes all listeners from each 
642         * property's change event and all listeners from the configChangedEvent.
643         * @method destroy
644         */
645         destroy: function () {
647             var oConfig = this.config,
648                 sProperty,
649                 oProperty;
652             for (sProperty in oConfig) {
653             
654                 if (Lang.hasOwnProperty(oConfig, sProperty)) {
656                     oProperty = oConfig[sProperty];
658                     oProperty.event.unsubscribeAll();
659                     oProperty.event = null;
661                 }
662             
663             }
664             
665             this.configChangedEvent.unsubscribeAll();
666             
667             this.configChangedEvent = null;
668             this.owner = null;
669             this.config = null;
670             this.initialConfig = null;
671             this.eventQueue = null;
672         
673         }
675     };
676     
677     
678     
679     /**
680     * Checks to determine if a particular function/Object pair are already 
681     * subscribed to the specified CustomEvent
682     * @method YAHOO.util.Config.alreadySubscribed
683     * @static
684     * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check 
685     * the subscriptions
686     * @param {Function} fn The function to look for in the subscribers list
687     * @param {Object} obj The execution scope Object for the subscription
688     * @return {Boolean} true, if the function/Object pair is already subscribed 
689     * to the CustomEvent passed in
690     */
691     Config.alreadySubscribed = function (evt, fn, obj) {
692     
693         var nSubscribers = evt.subscribers.length,
694             subsc,
695             i;
697         if (nSubscribers > 0) {
699             i = nSubscribers - 1;
700         
701             do {
703                 subsc = evt.subscribers[i];
705                 if (subsc && subsc.obj == obj && subsc.fn == fn) {
706         
707                     return true;
708         
709                 }    
710             
711             }
712             while (i--);
713         
714         }
715     
716         return false;
717     
718     };
719     
720     YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
722 }());
723 (function () {
725     /**
726     * The Container family of components is designed to enable developers to 
727     * create different kinds of content-containing modules on the web. Module 
728     * and Overlay are the most basic containers, and they can be used directly 
729     * or extended to build custom containers. Also part of the Container family 
730     * are four UI controls that extend Module and Overlay: Tooltip, Panel, 
731     * Dialog, and SimpleDialog.
732     * @module container
733     * @title Container
734     * @requires yahoo, dom, event 
735     * @optional dragdrop, animation, button
736     */
737     
738     /**
739     * Module is a JavaScript representation of the Standard Module Format. 
740     * Standard Module Format is a simple standard for markup containers where 
741     * child nodes representing the header, body, and footer of the content are 
742     * denoted using the CSS classes "hd", "bd", and "ft" respectively. 
743     * Module is the base class for all other classes in the YUI 
744     * Container package.
745     * @namespace YAHOO.widget
746     * @class Module
747     * @constructor
748     * @param {String} el The element ID representing the Module <em>OR</em>
749     * @param {HTMLElement} el The element representing the Module
750     * @param {Object} userConfig The configuration Object literal containing 
751     * the configuration that should be set for this module. See configuration 
752     * documentation for more details.
753     */
754     YAHOO.widget.Module = function (el, userConfig) {
755     
756         if (el) {
757     
758             this.init(el, userConfig);
759     
760         } else {
761     
762             YAHOO.log("No element or element ID specified" + 
763                 " for Module instantiation", "error");
764     
765         }
766     
767     };
770     var Dom = YAHOO.util.Dom,
771         Config = YAHOO.util.Config,
772         Event = YAHOO.util.Event,
773         CustomEvent = YAHOO.util.CustomEvent,
774         Module = YAHOO.widget.Module,
775         
776         m_oModuleTemplate,
777         m_oHeaderTemplate,
778         m_oBodyTemplate,
779         m_oFooterTemplate,
781         /**
782         * Constant representing the name of the Module's events
783         * @property EVENT_TYPES
784         * @private
785         * @final
786         * @type Object
787         */
788         EVENT_TYPES = {
789         
790             "BEFORE_INIT": "beforeInit",
791             "INIT": "init",
792             "APPEND": "append",
793             "BEFORE_RENDER": "beforeRender",
794             "RENDER": "render",
795             "CHANGE_HEADER": "changeHeader",
796             "CHANGE_BODY": "changeBody",
797             "CHANGE_FOOTER": "changeFooter",
798             "CHANGE_CONTENT": "changeContent",
799             "DESTORY": "destroy",
800             "BEFORE_SHOW": "beforeShow",
801             "SHOW": "show",
802             "BEFORE_HIDE": "beforeHide",
803             "HIDE": "hide"
804         
805         },
806             
807         /**
808         * Constant representing the Module's configuration properties
809         * @property DEFAULT_CONFIG
810         * @private
811         * @final
812         * @type Object
813         */
814         DEFAULT_CONFIG = {
815         
816             "VISIBLE": { 
817                 key: "visible", 
818                 value: true, 
819                 validator: YAHOO.lang.isBoolean 
820             },
821         
822             "EFFECT": { 
823                 key: "effect", 
824                 suppressEvent: true, 
825                 supercedes: ["visible"] 
826             },
827         
828             "MONITOR_RESIZE": { 
829                 key: "monitorresize", 
830                 value: true  
831             }
832         
833         };
835     
836     /**
837     * Constant representing the prefix path to use for non-secure images
838     * @property YAHOO.widget.Module.IMG_ROOT
839     * @static
840     * @final
841     * @type String
842     */
843     Module.IMG_ROOT = null;
844     
845     /**
846     * Constant representing the prefix path to use for securely served images
847     * @property YAHOO.widget.Module.IMG_ROOT_SSL
848     * @static
849     * @final
850     * @type String
851     */
852     Module.IMG_ROOT_SSL = null;
853     
854     /**
855     * Constant for the default CSS class name that represents a Module
856     * @property YAHOO.widget.Module.CSS_MODULE
857     * @static
858     * @final
859     * @type String
860     */
861     Module.CSS_MODULE = "yui-module";
862     
863     /**
864     * Constant representing the module header
865     * @property YAHOO.widget.Module.CSS_HEADER
866     * @static
867     * @final
868     * @type String
869     */
870     Module.CSS_HEADER = "hd";
871     
872     /**
873     * Constant representing the module body
874     * @property YAHOO.widget.Module.CSS_BODY
875     * @static
876     * @final
877     * @type String
878     */
879     Module.CSS_BODY = "bd";
880     
881     /**
882     * Constant representing the module footer
883     * @property YAHOO.widget.Module.CSS_FOOTER
884     * @static
885     * @final
886     * @type String
887     */
888     Module.CSS_FOOTER = "ft";
889     
890     /**
891     * Constant representing the url for the "src" attribute of the iframe 
892     * used to monitor changes to the browser's base font size
893     * @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
894     * @static
895     * @final
896     * @type String
897     */
898     Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
899     
900     /**
901     * Singleton CustomEvent fired when the font size is changed in the browser.
902     * Opera's "zoom" functionality currently does not support text 
903     * size detection.
904     * @event YAHOO.widget.Module.textResizeEvent
905     */
906     Module.textResizeEvent = new CustomEvent("textResize");
909     function createModuleTemplate() {
911         if (!m_oModuleTemplate) {
913             m_oModuleTemplate = document.createElement("div");
914             
915             m_oModuleTemplate.innerHTML = ("<div class=\"" + 
916                 Module.CSS_HEADER + "\"></div>" + "<div class=\"" + 
917                 Module.CSS_BODY + "\"></div><div class=\"" + 
918                 Module.CSS_FOOTER + "\"></div>");
920             m_oHeaderTemplate = m_oModuleTemplate.firstChild;
921             m_oBodyTemplate = m_oHeaderTemplate.nextSibling;
922             m_oFooterTemplate = m_oBodyTemplate.nextSibling;
924         }
926         return m_oModuleTemplate;
928     }
931     function createHeader() {
933         if (!m_oHeaderTemplate) {
934         
935             createModuleTemplate();
936         
937         }
938         
939         return (m_oHeaderTemplate.cloneNode(false));
941     }
942     
944     function createBody() {
946         if (!m_oBodyTemplate) {
947         
948             createModuleTemplate();
949         
950         }
951         
952         return (m_oBodyTemplate.cloneNode(false));
953     
954     }
955     
957     function createFooter() {
959         if (!m_oFooterTemplate) {
960         
961             createModuleTemplate();
962         
963         }
964         
965         return (m_oFooterTemplate.cloneNode(false));
967     }
968     
970     Module.prototype = {
971     
972         /**
973         * The class's constructor function
974         * @property contructor
975         * @type Function
976         */
977         constructor: Module,
978         
979         /**
980         * The main module element that contains the header, body, and footer
981         * @property element
982         * @type HTMLElement
983         */
984         element: null,
985         
986         /**
987         * The header element, denoted with CSS class "hd"
988         * @property header
989         * @type HTMLElement
990         */
991         header: null,
992         
993         /**
994         * The body element, denoted with CSS class "bd"
995         * @property body
996         * @type HTMLElement
997         */
998         body: null,
999         
1000         /**
1001         * The footer element, denoted with CSS class "ft"
1002         * @property footer
1003         * @type HTMLElement
1004         */
1005         footer: null,
1006         
1007         /**
1008         * The id of the element
1009         * @property id
1010         * @type String
1011         */
1012         id: null,
1013         
1014         /**
1015         * A string representing the root path for all images created by
1016         * a Module instance.
1017         * @deprecated It is recommend that any images for a Module be applied
1018         * via CSS using the "background-image" property.
1019         * @property imageRoot
1020         * @type String
1021         */
1022         imageRoot: Module.IMG_ROOT,
1023     
1024         /**
1025         * Initializes the custom events for Module which are fired 
1026         * automatically at appropriate times by the Module class.
1027         * @method initEvents
1028         */
1029         initEvents: function () {
1030         
1031             var SIGNATURE = CustomEvent.LIST;
1032         
1033             /**
1034             * CustomEvent fired prior to class initalization.
1035             * @event beforeInitEvent
1036             * @param {class} classRef class reference of the initializing 
1037             * class, such as this.beforeInitEvent.fire(Module)
1038             */
1039             this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT);
1040             this.beforeInitEvent.signature = SIGNATURE;
1041         
1042             /**
1043             * CustomEvent fired after class initalization.
1044             * @event initEvent
1045             * @param {class} classRef class reference of the initializing 
1046             * class, such as this.beforeInitEvent.fire(Module)
1047             */  
1048             this.initEvent = this.createEvent(EVENT_TYPES.INIT);
1049             this.initEvent.signature = SIGNATURE;
1050         
1051             /**
1052             * CustomEvent fired when the Module is appended to the DOM
1053             * @event appendEvent
1054             */
1055             this.appendEvent = this.createEvent(EVENT_TYPES.APPEND);
1056             this.appendEvent.signature = SIGNATURE;
1057         
1058             /**
1059             * CustomEvent fired before the Module is rendered
1060             * @event beforeRenderEvent
1061             */
1062             this.beforeRenderEvent = 
1063                 this.createEvent(EVENT_TYPES.BEFORE_RENDER);
1064             this.beforeRenderEvent.signature = SIGNATURE;
1065         
1066             /**
1067             * CustomEvent fired after the Module is rendered
1068             * @event renderEvent
1069             */
1070             this.renderEvent = this.createEvent(EVENT_TYPES.RENDER);
1071             this.renderEvent.signature = SIGNATURE;
1072         
1073             /**
1074             * CustomEvent fired when the header content of the Module 
1075             * is modified
1076             * @event changeHeaderEvent
1077             * @param {String/HTMLElement} content String/element representing 
1078             * the new header content
1079             */
1080             this.changeHeaderEvent = 
1081                 this.createEvent(EVENT_TYPES.CHANGE_HEADER);
1082             this.changeHeaderEvent.signature = SIGNATURE;
1083             
1084             /**
1085             * CustomEvent fired when the body content of the Module is modified
1086             * @event changeBodyEvent
1087             * @param {String/HTMLElement} content String/element representing 
1088             * the new body content
1089             */  
1090             this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY);
1091             this.changeBodyEvent.signature = SIGNATURE;
1092             
1093             /**
1094             * CustomEvent fired when the footer content of the Module 
1095             * is modified
1096             * @event changeFooterEvent
1097             * @param {String/HTMLElement} content String/element representing 
1098             * the new footer content
1099             */
1100             this.changeFooterEvent = 
1101                 this.createEvent(EVENT_TYPES.CHANGE_FOOTER);
1102             this.changeFooterEvent.signature = SIGNATURE;
1103         
1104             /**
1105             * CustomEvent fired when the content of the Module is modified
1106             * @event changeContentEvent
1107             */
1108             this.changeContentEvent = 
1109                 this.createEvent(EVENT_TYPES.CHANGE_CONTENT);
1110             this.changeContentEvent.signature = SIGNATURE;
1111         
1112             /**
1113             * CustomEvent fired when the Module is destroyed
1114             * @event destroyEvent
1115             */
1116             this.destroyEvent = this.createEvent(EVENT_TYPES.DESTORY);
1117             this.destroyEvent.signature = SIGNATURE;
1118             
1119             /**
1120             * CustomEvent fired before the Module is shown
1121             * @event beforeShowEvent
1122             */
1123             this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW);
1124             this.beforeShowEvent.signature = SIGNATURE;
1125         
1126             /**
1127             * CustomEvent fired after the Module is shown
1128             * @event showEvent
1129             */
1130             this.showEvent = this.createEvent(EVENT_TYPES.SHOW);
1131             this.showEvent.signature = SIGNATURE;
1132         
1133             /**
1134             * CustomEvent fired before the Module is hidden
1135             * @event beforeHideEvent
1136             */
1137             this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE);
1138             this.beforeHideEvent.signature = SIGNATURE;
1139         
1140             /**
1141             * CustomEvent fired after the Module is hidden
1142             * @event hideEvent
1143             */
1144             this.hideEvent = this.createEvent(EVENT_TYPES.HIDE);
1145             this.hideEvent.signature = SIGNATURE;
1146         }, 
1147         
1148         /**
1149         * String representing the current user-agent platform
1150         * @property platform
1151         * @type String
1152         */
1153         platform: function () {
1154         
1155             var ua = navigator.userAgent.toLowerCase();
1156         
1157             if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
1158         
1159                 return "windows";
1160         
1161             } else if (ua.indexOf("macintosh") != -1) {
1162         
1163                 return "mac";
1164         
1165             } else {
1166         
1167                 return false;
1168         
1169             }
1170         
1171         }(),
1172         
1173         /**
1174         * String representing the user-agent of the browser
1175         * @deprecated Use YAHOO.env.ua
1176         * @property browser
1177         * @type String
1178         */
1179         browser: function () {
1180         
1181             var ua = navigator.userAgent.toLowerCase();
1182             
1183             /*
1184                  Check Opera first in case of spoof and check Safari before
1185                  Gecko since Safari's user agent string includes "like Gecko"
1186             */
1188             if (ua.indexOf('opera') != -1) { 
1189             
1190                 return 'opera';
1191             
1192             } else if (ua.indexOf('msie 7') != -1) {
1193             
1194                 return 'ie7';
1195             
1196             } else if (ua.indexOf('msie') != -1) {
1197             
1198                 return 'ie';
1199             
1200             } else if (ua.indexOf('safari') != -1) { 
1201             
1202                 return 'safari';
1203             
1204             } else if (ua.indexOf('gecko') != -1) {
1205             
1206                 return 'gecko';
1207             
1208             } else {
1209             
1210                 return false;
1211             
1212             }
1213         
1214         }(),
1215         
1216         /**
1217         * Boolean representing whether or not the current browsing context is 
1218         * secure (https)
1219         * @property isSecure
1220         * @type Boolean
1221         */
1222         isSecure: function () {
1223         
1224             if (window.location.href.toLowerCase().indexOf("https") === 0) {
1225         
1226                 return true;
1227         
1228             } else {
1229         
1230                 return false;
1231         
1232             }
1233         
1234         }(),
1235         
1236         /**
1237         * Initializes the custom events for Module which are fired 
1238         * automatically at appropriate times by the Module class.
1239         */
1240         initDefaultConfig: function () {
1241     
1242             // Add properties //
1243         
1244             /**
1245             * Specifies whether the Module is visible on the page.
1246             * @config visible
1247             * @type Boolean
1248             * @default true
1249             */
1250             this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, {
1251                 handler: this.configVisible, 
1252                 value: DEFAULT_CONFIG.VISIBLE.value, 
1253                 validator: DEFAULT_CONFIG.VISIBLE.validator
1254             });
1255             
1256             /**
1257             * Object or array of objects representing the ContainerEffect 
1258             * classes that are active for animating the container.
1259             * @config effect
1260             * @type Object
1261             * @default null
1262             */
1263             this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, {
1264                 suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent, 
1265                 supercedes: DEFAULT_CONFIG.EFFECT.supercedes
1266             });
1267             
1268             /**
1269             * Specifies whether to create a special proxy iframe to monitor 
1270             * for user font resizing in the document
1271             * @config monitorresize
1272             * @type Boolean
1273             * @default true
1274             */
1275             this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, {
1276                 handler: this.configMonitorResize,
1277                 value: DEFAULT_CONFIG.MONITOR_RESIZE.value
1278             });
1279             
1280         },
1281         
1282         /**
1283         * The Module class's initialization method, which is executed for
1284         * Module and all of its subclasses. This method is automatically 
1285         * called by the constructor, and  sets up all DOM references for 
1286         * pre-existing markup, and creates required markup if it is not 
1287         * already present.
1288         * @method init
1289         * @param {String} el The element ID representing the Module <em>OR</em>
1290         * @param {HTMLElement} el The element representing the Module
1291         * @param {Object} userConfig The configuration Object literal 
1292         * containing the configuration that should be set for this module. 
1293         * See configuration documentation for more details.
1294         */
1295         init: function (el, userConfig) {
1296         
1297             var elId, i, child;
1298         
1299             this.initEvents();
1300         
1301             this.beforeInitEvent.fire(Module);
1302         
1303             /**
1304             * The Module's Config object used for monitoring 
1305             * configuration properties.
1306             * @property cfg
1307             * @type YAHOO.util.Config
1308             */
1309             this.cfg = new Config(this);
1310         
1311             if (this.isSecure) {
1312                 this.imageRoot = Module.IMG_ROOT_SSL;
1313             }
1314         
1315             if (typeof el == "string") {
1317                 elId = el;
1318         
1319                 el = document.getElementById(el);
1321                 if (! el) {
1323                     el = (createModuleTemplate()).cloneNode(false);
1325                     el.id = elId;
1327                 }
1329             }
1330         
1331             this.element = el;
1332         
1333             if (el.id) {
1334                 this.id = el.id;
1335             }
1336         
1337             child = this.element.firstChild;
1338             
1339             if (child) {
1341                 do {
1343                     switch (child.className) {
1344     
1345                     case Module.CSS_HEADER:
1346     
1347                         this.header = child;
1348     
1349                         break;
1350     
1351                     case Module.CSS_BODY:
1352     
1353                         this.body = child;
1354     
1355                         break;
1356     
1357                     case Module.CSS_FOOTER:
1358     
1359                         this.footer = child;
1360     
1361                         break;
1362     
1363                     }
1364                     
1365                 } while ((child = child.nextSibling));
1366             
1367             }
1369         
1370             this.initDefaultConfig();
1371         
1372             Dom.addClass(this.element, Module.CSS_MODULE);
1373         
1374             if (userConfig) {
1375                 this.cfg.applyConfig(userConfig, true);
1376             }
1377         
1378             /*
1379                 Subscribe to the fireQueue() method of Config so that any 
1380                 queued configuration changes are excecuted upon render of 
1381                 the Module
1382             */ 
1383             
1384             if (!Config.alreadySubscribed(this.renderEvent, 
1385                 this.cfg.fireQueue, this.cfg)) {
1387                 this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
1389             }
1390         
1391             this.initEvent.fire(Module);
1392         },
1393         
1394         /**
1395         * Initialized an empty IFRAME that is placed out of the visible area 
1396         * that can be used to detect text resize.
1397         * @method initResizeMonitor
1398         */
1399         initResizeMonitor: function () {
1400         
1401             var oDoc, 
1402                 oIFrame, 
1403                 sHTML;
1404         
1405             function fireTextResize() {
1406         
1407                 Module.textResizeEvent.fire();
1408         
1409             }
1410         
1411             if (!YAHOO.env.ua.opera) {
1412         
1413                 oIFrame = Dom.get("_yuiResizeMonitor");
1414         
1415                 if (!oIFrame) {
1416         
1417                     oIFrame = document.createElement("iframe");
1418         
1419                     if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && 
1420                         YAHOO.env.ua.ie) {
1421     
1422                         oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL;
1423     
1424                     }
1427                     /*
1428                         Need to set "src" attribute of the iframe to 
1429                         prevent the browser from reporting duplicate 
1430                         cookies. (See SourceForge bug #1721755)
1431                     */
1432         
1433                     if (YAHOO.env.ua.gecko) {
1435                         sHTML = "<html><head><script " +
1436                                 "type=\"text/javascript\">" + 
1437                                 "window.onresize=function(){window.parent." +
1438                                 "YAHOO.widget.Module.textResizeEvent." +
1439                                 "fire();};window.parent.YAHOO.widget.Module." +
1440                                 "textResizeEvent.fire();</script></head>" + 
1441                                 "<body></body></html>";
1443                         oIFrame.src = "data:text/html;charset=utf-8," + 
1444                             encodeURIComponent(sHTML);
1446                     }
1448                     oIFrame.id = "_yuiResizeMonitor";
1449                     
1450                     /*
1451                         Need to set "position" property before inserting the 
1452                         iframe into the document or Safari's status bar will 
1453                         forever indicate the iframe is loading 
1454                         (See SourceForge bug #1723064)
1455                     */
1456                     
1457                     oIFrame.style.position = "absolute";
1458                     oIFrame.style.visibility = "hidden";
1459         
1460                     document.body.appendChild(oIFrame);
1461         
1462                     oIFrame.style.width = "10em";
1463                     oIFrame.style.height = "10em";
1464                     oIFrame.style.top = (-1 * oIFrame.offsetHeight) + "px";
1465                     oIFrame.style.left = (-1 * oIFrame.offsetWidth) + "px";
1466                     oIFrame.style.borderWidth = "0";
1467                     oIFrame.style.visibility = "visible";
1468         
1469                     if (YAHOO.env.ua.webkit) {
1470         
1471                         oDoc = oIFrame.contentWindow.document;
1472         
1473                         oDoc.open();
1474                         oDoc.close();
1475         
1476                     }
1478                 }
1479         
1480                 if (oIFrame && oIFrame.contentWindow) {
1482                     Module.textResizeEvent.subscribe(this.onDomResize, 
1483                         this, true);
1484         
1485                     if (!Module.textResizeInitialized) {
1487                         if (!Event.on(oIFrame.contentWindow, "resize", 
1488                             fireTextResize)) {
1490                             /*
1491                                  This will fail in IE if document.domain has 
1492                                  changed, so we must change the listener to 
1493                                  use the oIFrame element instead
1494                             */
1496                             Event.on(oIFrame, "resize", fireTextResize);
1498                         }
1500                         Module.textResizeInitialized = true;
1502                     }
1504                     this.resizeMonitor = oIFrame;
1506                 }
1507         
1508             }
1509         
1510         },
1511         
1512         /**
1513         * Event handler fired when the resize monitor element is resized.
1514         * @method onDomResize
1515         * @param {DOMEvent} e The DOM resize event
1516         * @param {Object} obj The scope object passed to the handler
1517         */
1518         onDomResize: function (e, obj) {
1519         
1520             var nLeft = -1 * this.resizeMonitor.offsetWidth,
1521                 nTop = -1 * this.resizeMonitor.offsetHeight;
1522         
1523             this.resizeMonitor.style.top = nTop + "px";
1524             this.resizeMonitor.style.left =  nLeft + "px";
1525         
1526         },
1527         
1528         /**
1529         * Sets the Module's header content to the HTML specified, or appends 
1530         * the passed element to the header. If no header is present, one will 
1531         * be automatically created.
1532         * @method setHeader
1533         * @param {String} headerContent The HTML used to set the header 
1534         * <em>OR</em>
1535         * @param {HTMLElement} headerContent The HTMLElement to append to 
1536         * the header
1537         */
1538         setHeader: function (headerContent) {
1540             var oHeader = this.header || (this.header = createHeader());
1541         
1542             if (typeof headerContent == "string") {
1544                 oHeader.innerHTML = headerContent;
1546             } else {
1548                 oHeader.innerHTML = "";
1549                 oHeader.appendChild(headerContent);
1551             }
1552         
1553             this.changeHeaderEvent.fire(headerContent);
1554             this.changeContentEvent.fire();
1556         },
1557         
1558         /**
1559         * Appends the passed element to the header. If no header is present, 
1560         * one will be automatically created.
1561         * @method appendToHeader
1562         * @param {HTMLElement} element The element to append to the header
1563         */
1564         appendToHeader: function (element) {
1566             var oHeader = this.header || (this.header = createHeader());
1567         
1568             oHeader.appendChild(element);
1570             this.changeHeaderEvent.fire(element);
1571             this.changeContentEvent.fire();
1573         },
1574         
1575         /**
1576         * Sets the Module's body content to the HTML specified, or appends the
1577         * passed element to the body. If no body is present, one will be 
1578         * automatically created.
1579         * @method setBody
1580         * @param {String} bodyContent The HTML used to set the body <em>OR</em>
1581         * @param {HTMLElement} bodyContent The HTMLElement to append to the body
1582         */
1583         setBody: function (bodyContent) {
1585             var oBody = this.body || (this.body = createBody());
1586         
1587             if (typeof bodyContent == "string") {
1589                 oBody.innerHTML = bodyContent;
1591             } else {
1593                 oBody.innerHTML = "";
1594                 oBody.appendChild(bodyContent);
1596             }
1597         
1598             this.changeBodyEvent.fire(bodyContent);
1599             this.changeContentEvent.fire();
1601         },
1602         
1603         /**
1604         * Appends the passed element to the body. If no body is present, one 
1605         * will be automatically created.
1606         * @method appendToBody
1607         * @param {HTMLElement} element The element to append to the body
1608         */
1609         appendToBody: function (element) {
1611             var oBody = this.body || (this.body = createBody());
1612         
1613             oBody.appendChild(element);
1615             this.changeBodyEvent.fire(element);
1616             this.changeContentEvent.fire();
1618         },
1619         
1620         /**
1621         * Sets the Module's footer content to the HTML specified, or appends 
1622         * the passed element to the footer. If no footer is present, one will 
1623         * be automatically created.
1624         * @method setFooter
1625         * @param {String} footerContent The HTML used to set the footer 
1626         * <em>OR</em>
1627         * @param {HTMLElement} footerContent The HTMLElement to append to 
1628         * the footer
1629         */
1630         setFooter: function (footerContent) {
1632             var oFooter = this.footer || (this.footer = createFooter());
1633         
1634             if (typeof footerContent == "string") {
1636                 oFooter.innerHTML = footerContent;
1638             } else {
1640                 oFooter.innerHTML = "";
1641                 oFooter.appendChild(footerContent);
1643             }
1644         
1645             this.changeFooterEvent.fire(footerContent);
1646             this.changeContentEvent.fire();
1648         },
1649         
1650         /**
1651         * Appends the passed element to the footer. If no footer is present, 
1652         * one will be automatically created.
1653         * @method appendToFooter
1654         * @param {HTMLElement} element The element to append to the footer
1655         */
1656         appendToFooter: function (element) {
1658             var oFooter = this.footer || (this.footer = createFooter());
1659         
1660             oFooter.appendChild(element);
1662             this.changeFooterEvent.fire(element);
1663             this.changeContentEvent.fire();
1665         },
1666         
1667         /**
1668         * Renders the Module by inserting the elements that are not already 
1669         * in the main Module into their correct places. Optionally appends 
1670         * the Module to the specified node prior to the render's execution. 
1671         * NOTE: For Modules without existing markup, the appendToNode argument 
1672         * is REQUIRED. If this argument is ommitted and the current element is 
1673         * not present in the document, the function will return false, 
1674         * indicating that the render was a failure.
1675         * @method render
1676         * @param {String} appendToNode The element id to which the Module 
1677         * should be appended to prior to rendering <em>OR</em>
1678         * @param {HTMLElement} appendToNode The element to which the Module 
1679         * should be appended to prior to rendering
1680         * @param {HTMLElement} moduleElement OPTIONAL. The element that 
1681         * represents the actual Standard Module container.
1682         * @return {Boolean} Success or failure of the render
1683         */
1684         render: function (appendToNode, moduleElement) {
1685         
1686             var me = this,
1687                 firstChild;
1688         
1689             function appendTo(element) {
1690                 if (typeof element == "string") {
1691                     element = document.getElementById(element);
1692                 }
1693         
1694                 if (element) {
1695                     element.appendChild(me.element);
1696                     me.appendEvent.fire();
1697                 }
1698             }
1699         
1700             this.beforeRenderEvent.fire();
1701         
1702             if (! moduleElement) {
1703                 moduleElement = this.element;
1704             }
1705         
1706             if (appendToNode) {
1708                 appendTo(appendToNode);
1710             } else { 
1712                 /*
1713                      No node was passed in. If the element is not already in 
1714                      the Dom, this fails
1715                 */
1717                 if (! Dom.inDocument(this.element)) {
1719                     YAHOO.log("Render failed. Must specify appendTo node if " + 
1720                         " Module isn't already in the DOM.", "error");
1722                     return false;
1724                 }
1726             }
1727         
1728             // Need to get everything into the DOM if it isn't already
1729         
1730             if (this.header && ! Dom.inDocument(this.header)) {
1732                 /*
1733                     There is a header, but it's not in the DOM yet... 
1734                     need to add it
1735                 */
1737                 firstChild = moduleElement.firstChild;
1739                 if (firstChild) { // Insert before first child if exists
1741                     moduleElement.insertBefore(this.header, firstChild);
1743                 } else { // Append to empty body because there are no children
1745                     moduleElement.appendChild(this.header);
1747                 }
1749             }
1750         
1751             if (this.body && ! Dom.inDocument(this.body)) {
1753                 /*
1754                      There is a body, but it's not in the DOM yet... 
1755                      need to add it
1756                 */
1759                 // Insert before footer if exists in DOM
1761                 if (this.footer && Dom.isAncestor(
1762                     this.moduleElement, this.footer)) { 
1764                     moduleElement.insertBefore(this.body, this.footer);
1766                 } else { // Append to element because there is no footer
1768                     moduleElement.appendChild(this.body);
1770                 }
1772             }
1773         
1774             if (this.footer && ! Dom.inDocument(this.footer)) {
1776                 /*
1777                      There is a footer, but it's not in the DOM yet... 
1778                      need to add it
1779                 */
1781                 moduleElement.appendChild(this.footer);
1783             }
1784         
1785             this.renderEvent.fire();
1786             return true;
1787         },
1788         
1789         /**
1790         * Removes the Module element from the DOM and sets all child elements 
1791         * to null.
1792         * @method destroy
1793         */
1794         destroy: function () {
1795         
1796             var parent,
1797                 e;
1798         
1799             if (this.element) {
1800                 Event.purgeElement(this.element, true);
1801                 parent = this.element.parentNode;
1802             }
1804             if (parent) {
1805                 parent.removeChild(this.element);
1806             }
1807         
1808             this.element = null;
1809             this.header = null;
1810             this.body = null;
1811             this.footer = null;
1813             Module.textResizeEvent.unsubscribe(this.onDomResize, this);
1815             this.cfg.destroy();
1816             this.cfg = null;
1818             this.destroyEvent.fire();
1819         
1820             for (e in this) {
1821                 if (e instanceof CustomEvent) {
1822                     e.unsubscribeAll();
1823                 }
1824             }
1826         },
1827         
1828         /**
1829         * Shows the Module element by setting the visible configuration 
1830         * property to true. Also fires two events: beforeShowEvent prior to 
1831         * the visibility change, and showEvent after.
1832         * @method show
1833         */
1834         show: function () {
1835             this.cfg.setProperty("visible", true);
1836         },
1837         
1838         /**
1839         * Hides the Module element by setting the visible configuration 
1840         * property to false. Also fires two events: beforeHideEvent prior to 
1841         * the visibility change, and hideEvent after.
1842         * @method hide
1843         */
1844         hide: function () {
1845             this.cfg.setProperty("visible", false);
1846         },
1847         
1848         // BUILT-IN EVENT HANDLERS FOR MODULE //
1849         
1850         /**
1851         * Default event handler for changing the visibility property of a 
1852         * Module. By default, this is achieved by switching the "display" style 
1853         * between "block" and "none".
1854         * This method is responsible for firing showEvent and hideEvent.
1855         * @param {String} type The CustomEvent type (usually the property name)
1856         * @param {Object[]} args The CustomEvent arguments. For configuration 
1857         * handlers, args[0] will equal the newly applied value for the property.
1858         * @param {Object} obj The scope object. For configuration handlers, 
1859         * this will usually equal the owner.
1860         * @method configVisible
1861         */
1862         configVisible: function (type, args, obj) {
1863             var visible = args[0];
1864             if (visible) {
1865                 this.beforeShowEvent.fire();
1866                 Dom.setStyle(this.element, "display", "block");
1867                 this.showEvent.fire();
1868             } else {
1869                 this.beforeHideEvent.fire();
1870                 Dom.setStyle(this.element, "display", "none");
1871                 this.hideEvent.fire();
1872             }
1873         },
1874         
1875         /**
1876         * Default event handler for the "monitorresize" configuration property
1877         * @param {String} type The CustomEvent type (usually the property name)
1878         * @param {Object[]} args The CustomEvent arguments. For configuration 
1879         * handlers, args[0] will equal the newly applied value for the property.
1880         * @param {Object} obj The scope object. For configuration handlers, 
1881         * this will usually equal the owner.
1882         * @method configMonitorResize
1883         */
1884         configMonitorResize: function (type, args, obj) {
1886             var monitor = args[0];
1888             if (monitor) {
1890                 this.initResizeMonitor();
1892             } else {
1894                 Module.textResizeEvent.unsubscribe(
1895                     this.onDomResize, this, true);
1897                 this.resizeMonitor = null;
1898             }
1900         },
1901         
1902         /**
1903         * Returns a String representation of the Object.
1904         * @method toString
1905         * @return {String} The string representation of the Module
1906         */
1907         toString: function () {
1908             return "Module " + this.id;
1909         }
1910         
1911     };
1912     
1913     YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
1915 }());
1916 (function () {
1918     /**
1919     * Overlay is a Module that is absolutely positioned above the page flow. It 
1920     * has convenience methods for positioning and sizing, as well as options for 
1921     * controlling zIndex and constraining the Overlay's position to the current 
1922     * visible viewport. Overlay also contains a dynamicly generated IFRAME which 
1923     * is placed beneath it for Internet Explorer 6 and 5.x so that it will be 
1924     * properly rendered above SELECT elements.
1925     * @namespace YAHOO.widget
1926     * @class Overlay
1927     * @extends Module
1928     * @param {String} el The element ID representing the Overlay <em>OR</em>
1929     * @param {HTMLElement} el The element representing the Overlay
1930     * @param {Object} userConfig The configuration object literal containing 
1931     * the configuration that should be set for this Overlay. See configuration 
1932     * documentation for more details.
1933     * @constructor
1934     */
1935     YAHOO.widget.Overlay = function (el, userConfig) {
1936     
1937         YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
1938     
1939     };
1942     var Lang = YAHOO.lang,
1943         CustomEvent = YAHOO.util.CustomEvent,
1944         Module = YAHOO.widget.Module,
1945         Event = YAHOO.util.Event,
1946         Dom = YAHOO.util.Dom,
1947         Config = YAHOO.util.Config,
1948         Overlay = YAHOO.widget.Overlay,
1949         
1950         m_oIFrameTemplate,
1952         /**
1953         * Constant representing the name of the Overlay's events
1954         * @property EVENT_TYPES
1955         * @private
1956         * @final
1957         * @type Object
1958         */
1959         EVENT_TYPES = {
1960         
1961             "BEFORE_MOVE": "beforeMove",
1962             "MOVE": "move"
1963         
1964         },
1965         
1966         /**
1967         * Constant representing the Overlay's configuration properties
1968         * @property DEFAULT_CONFIG
1969         * @private
1970         * @final
1971         * @type Object
1972         */
1973         DEFAULT_CONFIG = {
1974         
1975             "X": { 
1976                 key: "x", 
1977                 validator: Lang.isNumber, 
1978                 suppressEvent: true, 
1979                 supercedes: ["iframe"] 
1980             },
1981         
1982             "Y": { 
1983                 key: "y", 
1984                 validator: Lang.isNumber, 
1985                 suppressEvent: true, 
1986                 supercedes: ["iframe"] 
1987             },
1988         
1989             "XY": { 
1990                 key: "xy", 
1991                 suppressEvent: true, 
1992                 supercedes: ["iframe"] 
1993             },
1994         
1995             "CONTEXT": { 
1996                 key: "context", 
1997                 suppressEvent: true, 
1998                 supercedes: ["iframe"] 
1999             },
2000         
2001             "FIXED_CENTER": { 
2002                 key: "fixedcenter", 
2003                 value: false, 
2004                 validator: Lang.isBoolean, 
2005                 supercedes: ["iframe", "visible"] 
2006             },
2007         
2008             "WIDTH": { 
2009                 key: "width", 
2010                 suppressEvent: true, 
2011                 supercedes: ["context", "fixedcenter", "iframe"] 
2012             }, 
2013         
2014             "HEIGHT": { 
2015                 key: "height", 
2016                 suppressEvent: true, 
2017                 supercedes: ["context", "fixedcenter", "iframe"] 
2018             }, 
2019         
2020             "ZINDEX": { 
2021                 key: "zindex", 
2022                 value: null 
2023             }, 
2024         
2025             "CONSTRAIN_TO_VIEWPORT": { 
2026                 key: "constraintoviewport", 
2027                 value: false, 
2028                 validator: Lang.isBoolean, 
2029                 supercedes: ["iframe", "x", "y", "xy"] 
2030             }, 
2031         
2032             "IFRAME": { 
2033                 key: "iframe", 
2034                 value: (YAHOO.env.ua.ie == 6 ? true : false), 
2035                 validator: Lang.isBoolean, 
2036                 supercedes: ["zindex"] 
2037             }
2038         
2039         };
2042     /**
2043     * The URL that will be placed in the iframe
2044     * @property YAHOO.widget.Overlay.IFRAME_SRC
2045     * @static
2046     * @final
2047     * @type String
2048     */
2049     Overlay.IFRAME_SRC = "javascript:false;";
2051     /**
2052     * Number representing how much the iframe shim should be offset from each 
2053     * side of an Overlay instance.
2054     * @property YAHOO.widget.Overlay.IFRAME_SRC
2055     * @default 3
2056     * @static
2057     * @final
2058     * @type Number
2059     */
2060     Overlay.IFRAME_OFFSET = 3;
2061     
2062     /**
2063     * Constant representing the top left corner of an element, used for 
2064     * configuring the context element alignment
2065     * @property YAHOO.widget.Overlay.TOP_LEFT
2066     * @static
2067     * @final
2068     * @type String
2069     */
2070     Overlay.TOP_LEFT = "tl";
2071     
2072     /**
2073     * Constant representing the top right corner of an element, used for 
2074     * configuring the context element alignment
2075     * @property YAHOO.widget.Overlay.TOP_RIGHT
2076     * @static
2077     * @final
2078     * @type String
2079     */
2080     Overlay.TOP_RIGHT = "tr";
2081     
2082     /**
2083     * Constant representing the top bottom left corner of an element, used for 
2084     * configuring the context element alignment
2085     * @property YAHOO.widget.Overlay.BOTTOM_LEFT
2086     * @static
2087     * @final
2088     * @type String
2089     */
2090     Overlay.BOTTOM_LEFT = "bl";
2091     
2092     /**
2093     * Constant representing the bottom right corner of an element, used for 
2094     * configuring the context element alignment
2095     * @property YAHOO.widget.Overlay.BOTTOM_RIGHT
2096     * @static
2097     * @final
2098     * @type String
2099     */
2100     Overlay.BOTTOM_RIGHT = "br";
2101     
2102     /**
2103     * Constant representing the default CSS class used for an Overlay
2104     * @property YAHOO.widget.Overlay.CSS_OVERLAY
2105     * @static
2106     * @final
2107     * @type String
2108     */
2109     Overlay.CSS_OVERLAY = "yui-overlay";
2110     
2111     
2112     /**
2113     * A singleton CustomEvent used for reacting to the DOM event for 
2114     * window scroll
2115     * @event YAHOO.widget.Overlay.windowScrollEvent
2116     */
2117     Overlay.windowScrollEvent = new CustomEvent("windowScroll");
2118     
2119     /**
2120     * A singleton CustomEvent used for reacting to the DOM event for
2121     * window resize
2122     * @event YAHOO.widget.Overlay.windowResizeEvent
2123     */
2124     Overlay.windowResizeEvent = new CustomEvent("windowResize");
2125     
2126     /**
2127     * The DOM event handler used to fire the CustomEvent for window scroll
2128     * @method YAHOO.widget.Overlay.windowScrollHandler
2129     * @static
2130     * @param {DOMEvent} e The DOM scroll event
2131     */
2132     Overlay.windowScrollHandler = function (e) {
2133     
2134         if (YAHOO.env.ua.ie) {
2135     
2136             if (! window.scrollEnd) {
2137     
2138                 window.scrollEnd = -1;
2139     
2140             }
2141     
2142             clearTimeout(window.scrollEnd);
2143     
2144             window.scrollEnd = setTimeout(function () { 
2145             
2146                 Overlay.windowScrollEvent.fire(); 
2147     
2148             }, 1);
2149     
2150         } else {
2151     
2152             Overlay.windowScrollEvent.fire();
2153     
2154         }
2155     
2156     };
2157     
2158     /**
2159     * The DOM event handler used to fire the CustomEvent for window resize
2160     * @method YAHOO.widget.Overlay.windowResizeHandler
2161     * @static
2162     * @param {DOMEvent} e The DOM resize event
2163     */
2164     Overlay.windowResizeHandler = function (e) {
2165     
2166         if (YAHOO.env.ua.ie) {
2167     
2168             if (! window.resizeEnd) {
2169                 window.resizeEnd = -1;
2170             }
2171     
2172             clearTimeout(window.resizeEnd);
2173     
2174             window.resizeEnd = setTimeout(function () {
2175     
2176                 Overlay.windowResizeEvent.fire(); 
2177     
2178             }, 100);
2179     
2180         } else {
2181     
2182             Overlay.windowResizeEvent.fire();
2183     
2184         }
2185     
2186     };
2187     
2188     /**
2189     * A boolean that indicated whether the window resize and scroll events have 
2190     * already been subscribed to.
2191     * @property YAHOO.widget.Overlay._initialized
2192     * @private
2193     * @type Boolean
2194     */
2195     Overlay._initialized = null;
2196     
2197     if (Overlay._initialized === null) {
2198     
2199         Event.on(window, "scroll", Overlay.windowScrollHandler);
2200         Event.on(window, "resize", Overlay.windowResizeHandler);
2201     
2202         Overlay._initialized = true;
2203     
2204     }
2205     
2206     YAHOO.extend(Overlay, Module, {
2207     
2208         /**
2209         * The Overlay initialization method, which is executed for Overlay and  
2210         * all of its subclasses. This method is automatically called by the 
2211         * constructor, and  sets up all DOM references for pre-existing markup, 
2212         * and creates required markup if it is not already present.
2213         * @method init
2214         * @param {String} el The element ID representing the Overlay <em>OR</em>
2215         * @param {HTMLElement} el The element representing the Overlay
2216         * @param {Object} userConfig The configuration object literal 
2217         * containing the configuration that should be set for this Overlay. 
2218         * See configuration documentation for more details.
2219         */
2220         init: function (el, userConfig) {
2221     
2222             /*
2223                  Note that we don't pass the user config in here yet because we
2224                  only want it executed once, at the lowest subclass level
2225             */
2226     
2227             Overlay.superclass.init.call(this, el/*, userConfig*/);  
2228             
2229             this.beforeInitEvent.fire(Overlay);
2230             
2231             Dom.addClass(this.element, Overlay.CSS_OVERLAY);
2232             
2233             if (userConfig) {
2234     
2235                 this.cfg.applyConfig(userConfig, true);
2236     
2237             }
2238             
2239             if (this.platform == "mac" && YAHOO.env.ua.gecko) {
2240     
2241                 if (! Config.alreadySubscribed(this.showEvent,
2242                     this.showMacGeckoScrollbars, this)) {
2243     
2244                     this.showEvent.subscribe(this.showMacGeckoScrollbars, 
2245                         this, true);
2246     
2247                 }
2248     
2249                 if (! Config.alreadySubscribed(this.hideEvent, 
2250                     this.hideMacGeckoScrollbars, this)) {
2251     
2252                     this.hideEvent.subscribe(this.hideMacGeckoScrollbars, 
2253                         this, true);
2254     
2255                 }
2256     
2257             }
2258             
2259             this.initEvent.fire(Overlay);
2260         
2261         },
2262         
2263         /**
2264         * Initializes the custom events for Overlay which are fired  
2265         * automatically at appropriate times by the Overlay class.
2266         * @method initEvents
2267         */
2268         initEvents: function () {
2269     
2270             Overlay.superclass.initEvents.call(this);
2271             
2272             var SIGNATURE = CustomEvent.LIST;
2273             
2274             /**
2275             * CustomEvent fired before the Overlay is moved.
2276             * @event beforeMoveEvent
2277             * @param {Number} x x coordinate
2278             * @param {Number} y y coordinate
2279             */
2280             this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
2281             this.beforeMoveEvent.signature = SIGNATURE;
2282             
2283             /**
2284             * CustomEvent fired after the Overlay is moved.
2285             * @event moveEvent
2286             * @param {Number} x x coordinate
2287             * @param {Number} y y coordinate
2288             */
2289             this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
2290             this.moveEvent.signature = SIGNATURE;
2291         
2292         },
2293         
2294         /**
2295         * Initializes the class's configurable properties which can be changed 
2296         * using the Overlay's Config object (cfg).
2297         * @method initDefaultConfig
2298         */
2299         initDefaultConfig: function () {
2300     
2301             Overlay.superclass.initDefaultConfig.call(this);
2302             
2303             
2304             // Add overlay config properties //
2305             
2306             /**
2307             * The absolute x-coordinate position of the Overlay
2308             * @config x
2309             * @type Number
2310             * @default null
2311             */
2312             this.cfg.addProperty(DEFAULT_CONFIG.X.key, { 
2313     
2314                 handler: this.configX, 
2315                 validator: DEFAULT_CONFIG.X.validator, 
2316                 suppressEvent: DEFAULT_CONFIG.X.suppressEvent, 
2317                 supercedes: DEFAULT_CONFIG.X.supercedes
2318     
2319             });
2320         
2321     
2322             /**
2323             * The absolute y-coordinate position of the Overlay
2324             * @config y
2325             * @type Number
2326             * @default null
2327             */
2328             this.cfg.addProperty(DEFAULT_CONFIG.Y.key, {
2329     
2330                 handler: this.configY, 
2331                 validator: DEFAULT_CONFIG.Y.validator, 
2332                 suppressEvent: DEFAULT_CONFIG.Y.suppressEvent, 
2333                 supercedes: DEFAULT_CONFIG.Y.supercedes
2334     
2335             });
2336         
2337     
2338             /**
2339             * An array with the absolute x and y positions of the Overlay
2340             * @config xy
2341             * @type Number[]
2342             * @default null
2343             */
2344             this.cfg.addProperty(DEFAULT_CONFIG.XY.key, {
2345             
2346                 handler: this.configXY, 
2347                 suppressEvent: DEFAULT_CONFIG.XY.suppressEvent, 
2348                 supercedes: DEFAULT_CONFIG.XY.supercedes
2349             
2350             });
2351         
2352     
2353             /**
2354             * The array of context arguments for context-sensitive positioning.  
2355             * The format is: [id or element, element corner, context corner]. 
2356             * For example, setting this property to ["img1", "tl", "bl"] would 
2357             * align the Overlay's top left corner to the context element's 
2358             * bottom left corner.
2359             * @config context
2360             * @type Array
2361             * @default null
2362             */
2363             this.cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
2364             
2365                 handler: this.configContext, 
2366                 suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent, 
2367                 supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
2368             
2369             });
2370         
2371     
2372             /**
2373             * True if the Overlay should be anchored to the center of 
2374             * the viewport.
2375             * @config fixedcenter
2376             * @type Boolean
2377             * @default false
2378             */
2379             this.cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
2380             
2381                 handler: this.configFixedCenter,
2382                 value: DEFAULT_CONFIG.FIXED_CENTER.value, 
2383                 validator: DEFAULT_CONFIG.FIXED_CENTER.validator, 
2384                 supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
2385             
2386             });
2387         
2388     
2389             /**
2390             * CSS width of the Overlay.
2391             * @config width
2392             * @type String
2393             * @default null
2394             */
2395             this.cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
2396             
2397                 handler: this.configWidth, 
2398                 suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent, 
2399                 supercedes: DEFAULT_CONFIG.WIDTH.supercedes
2400             
2401             });
2402             
2403             /**
2404             * CSS height of the Overlay.
2405             * @config height
2406             * @type String
2407             * @default null
2408             */
2409             this.cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
2410             
2411                 handler: this.configHeight, 
2412                 suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent, 
2413                 supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
2414             
2415             });
2416             
2417             /**
2418             * CSS z-index of the Overlay.
2419             * @config zIndex
2420             * @type Number
2421             * @default null
2422             */
2423             this.cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
2424     
2425                 handler: this.configzIndex,
2426                 value: DEFAULT_CONFIG.ZINDEX.value
2427     
2428             });
2429             
2430             /**
2431             * True if the Overlay should be prevented from being positioned 
2432             * out of the viewport.
2433             * @config constraintoviewport
2434             * @type Boolean
2435             * @default false
2436             */
2437             this.cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
2438             
2439                 handler: this.configConstrainToViewport, 
2440                 value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value, 
2441                 validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator, 
2442                 supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
2443             
2444             });
2445             
2446             /**
2447             * @config iframe
2448             * @description Boolean indicating whether or not the Overlay should 
2449             * have an IFRAME shim; used to prevent <SELECT> elements from 
2450             * poking through an Overlay instance in IE6.  When set to "true", 
2451             * the iframe shim is created when the Overlay instance is intially
2452             * made visible.
2453             * @type Boolean
2454             * @default true for IE6 and below, false for all other browsers.
2455             */
2456             this.cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
2457             
2458                 handler: this.configIframe, 
2459                 value: DEFAULT_CONFIG.IFRAME.value, 
2460                 validator: DEFAULT_CONFIG.IFRAME.validator, 
2461                 supercedes: DEFAULT_CONFIG.IFRAME.supercedes
2462             
2463             });
2464         
2465         },
2466         
2467         /**
2468         * Moves the Overlay to the specified position. This function is  
2469         * identical to calling this.cfg.setProperty("xy", [x,y]);
2470         * @method moveTo
2471         * @param {Number} x The Overlay's new x position
2472         * @param {Number} y The Overlay's new y position
2473         */
2474         moveTo: function (x, y) {
2475     
2476             this.cfg.setProperty("xy", [x, y]);
2477     
2478         },
2479         
2480         /**
2481         * Adds a CSS class ("hide-scrollbars") and removes a CSS class 
2482         * ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2483         * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2484         * @method hideMacGeckoScrollbars
2485         */
2486         hideMacGeckoScrollbars: function () {
2487     
2488             Dom.removeClass(this.element, "show-scrollbars");
2489             Dom.addClass(this.element, "hide-scrollbars");
2490     
2491         },
2492         
2493         /**
2494         * Adds a CSS class ("show-scrollbars") and removes a CSS class 
2495         * ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2496         * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2497         * @method showMacGeckoScrollbars
2498         */
2499         showMacGeckoScrollbars: function () {
2500     
2501             Dom.removeClass(this.element, "hide-scrollbars");
2502             Dom.addClass(this.element, "show-scrollbars");
2503     
2504         },
2505         
2506         // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
2507         
2508         /**
2509         * The default event handler fired when the "visible" property is 
2510         * changed.  This method is responsible for firing showEvent
2511         * and hideEvent.
2512         * @method configVisible
2513         * @param {String} type The CustomEvent type (usually the property name)
2514         * @param {Object[]} args The CustomEvent arguments. For configuration
2515         * handlers, args[0] will equal the newly applied value for the property.
2516         * @param {Object} obj The scope object. For configuration handlers, 
2517         * this will usually equal the owner.
2518         */
2519         configVisible: function (type, args, obj) {
2520     
2521             var visible = args[0],
2522                 currentVis = Dom.getStyle(this.element, "visibility"),
2523                 effect = this.cfg.getProperty("effect"),
2524                 effectInstances = [],
2525                 isMacGecko = (this.platform == "mac" && YAHOO.env.ua.gecko),
2526                 alreadySubscribed = Config.alreadySubscribed,
2527                 eff, ei, e, i, j, k, h,
2528                 nEffects,
2529                 nEffectInstances;
2530     
2531     
2532             if (currentVis == "inherit") {
2533     
2534                 e = this.element.parentNode;
2535     
2536                 while (e.nodeType != 9 && e.nodeType != 11) {
2537     
2538                     currentVis = Dom.getStyle(e, "visibility");
2539     
2540                     if (currentVis != "inherit") { 
2541     
2542                         break; 
2543     
2544                     }
2545     
2546                     e = e.parentNode;
2547     
2548                 }
2549     
2550                 if (currentVis == "inherit") {
2551     
2552                     currentVis = "visible";
2553                 
2554                 }
2555     
2556             }
2557         
2558     
2559             if (effect) {
2560     
2561                 if (effect instanceof Array) {
2563                     nEffects = effect.length;
2564     
2565                     for (i = 0; i < nEffects; i++) {
2566     
2567                         eff = effect[i];
2568     
2569                         effectInstances[effectInstances.length] = 
2570                             eff.effect(this, eff.duration);
2571     
2572                     }
2573     
2574                 } else {
2575     
2576                     effectInstances[effectInstances.length] = 
2577                         effect.effect(this, effect.duration);
2578     
2579                 }
2580     
2581             }
2582     
2583         
2584             if (visible) { // Show
2585     
2586                 if (isMacGecko) {
2587     
2588                     this.showMacGeckoScrollbars();
2589     
2590                 }
2591                 
2592     
2593                 if (effect) { // Animate in
2594     
2595     
2596                     if (visible) { // Animate in if not showing
2597     
2598     
2599                         if (currentVis != "visible" || currentVis === "") {
2600     
2601                             this.beforeShowEvent.fire();
2603                             nEffectInstances = effectInstances.length;
2604     
2605                             for (j = 0; j < nEffectInstances; j++) {
2606     
2607                                 ei = effectInstances[j];
2608     
2609                                 if (j === 0 && !alreadySubscribed(
2610                                         ei.animateInCompleteEvent, 
2611                                         this.showEvent.fire, this.showEvent)) {
2612     
2613                                     /*
2614                                          Delegate showEvent until end 
2615                                          of animateInComplete
2616                                     */
2617     
2618                                     ei.animateInCompleteEvent.subscribe(
2619                                      this.showEvent.fire, this.showEvent, true);
2620     
2621                                 }
2622     
2623                                 ei.animateIn();
2624     
2625                             }
2626     
2627                         }
2628     
2629                     }
2630     
2631                 } else { // Show
2632     
2633                     if (currentVis != "visible" || currentVis === "") {
2634     
2635                         this.beforeShowEvent.fire();
2636     
2637                         Dom.setStyle(this.element, "visibility", "visible");
2638     
2639                         this.cfg.refireEvent("iframe");
2640                         this.showEvent.fire();
2641     
2642                     }
2643         
2644                 }
2645         
2646             } else { // Hide
2647     
2648                 if (isMacGecko) {
2649     
2650                     this.hideMacGeckoScrollbars();
2651     
2652                 }
2653                     
2654                 if (effect) { // Animate out if showing
2655     
2656                     if (currentVis == "visible") {
2657     
2658                         this.beforeHideEvent.fire();
2660                         nEffectInstances = effectInstances.length;
2661     
2662                         for (k = 0; k < nEffectInstances; k++) {
2663     
2664                             h = effectInstances[k];
2665     
2666                             if (k === 0 && !alreadySubscribed(
2667                                 h.animateOutCompleteEvent, this.hideEvent.fire, 
2668                                 this.hideEvent)) {
2669     
2670                                 /*
2671                                      Delegate hideEvent until end 
2672                                      of animateOutComplete
2673                                 */
2674     
2675                                 h.animateOutCompleteEvent.subscribe(
2676                                     this.hideEvent.fire, this.hideEvent, true);
2677     
2678                             }
2679     
2680                             h.animateOut();
2681     
2682                         }
2683     
2684                     } else if (currentVis === "") {
2685     
2686                         Dom.setStyle(this.element, "visibility", "hidden");
2687     
2688                     }
2689     
2690                 } else { // Simple hide
2691     
2692                     if (currentVis == "visible" || currentVis === "") {
2693     
2694                         this.beforeHideEvent.fire();
2695     
2696                         Dom.setStyle(this.element, "visibility", "hidden");
2698                         this.hideEvent.fire();
2699     
2700                     }
2701     
2702                 }
2703     
2704             }
2705     
2706         },
2707         
2708         /**
2709         * Center event handler used for centering on scroll/resize, but only if 
2710         * the Overlay is visible
2711         * @method doCenterOnDOMEvent
2712         */
2713         doCenterOnDOMEvent: function () {
2714     
2715             if (this.cfg.getProperty("visible")) {
2716     
2717                 this.center();
2718     
2719             }
2720     
2721         },
2722         
2723         /**
2724         * The default event handler fired when the "fixedcenter" property 
2725         * is changed.
2726         * @method configFixedCenter
2727         * @param {String} type The CustomEvent type (usually the property name)
2728         * @param {Object[]} args The CustomEvent arguments. For configuration 
2729         * handlers, args[0] will equal the newly applied value for the property.
2730         * @param {Object} obj The scope object. For configuration handlers, 
2731         * this will usually equal the owner.
2732         */
2733         configFixedCenter: function (type, args, obj) {
2734     
2735             var val = args[0],
2736                 alreadySubscribed = Config.alreadySubscribed,
2737                 windowResizeEvent = Overlay.windowResizeEvent,
2738                 windowScrollEvent = Overlay.windowScrollEvent;
2739             
2740             if (val) {
2741     
2742                 this.center();
2743             
2744                 if (!alreadySubscribed(this.beforeShowEvent, 
2745                     this.center, this)) {
2746     
2747                     this.beforeShowEvent.subscribe(this.center);
2748     
2749                 }
2750             
2751                 if (!alreadySubscribed(windowResizeEvent, 
2752                     this.doCenterOnDOMEvent, this)) {
2753     
2754                     windowResizeEvent.subscribe(this.doCenterOnDOMEvent, 
2755                         this, true);
2756     
2757                 }
2758             
2759                 if (!alreadySubscribed(windowScrollEvent, 
2760                     this.doCenterOnDOMEvent, this)) {
2761         
2762                     windowScrollEvent.subscribe(this.doCenterOnDOMEvent, 
2763                         this, true);
2764     
2765                 }
2766     
2767             } else {
2768     
2769                 this.beforeShowEvent.unsubscribe(this.center);
2770     
2771                 windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2772                 windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2773     
2774             }
2775     
2776         },
2777         
2778         /**
2779         * The default event handler fired when the "height" property is changed.
2780         * @method configHeight
2781         * @param {String} type The CustomEvent type (usually the property name)
2782         * @param {Object[]} args The CustomEvent arguments. For configuration 
2783         * handlers, args[0] will equal the newly applied value for the property.
2784         * @param {Object} obj The scope object. For configuration handlers, 
2785         * this will usually equal the owner.
2786         */
2787         configHeight: function (type, args, obj) {
2788     
2789             var height = args[0],
2790                 el = this.element;
2791     
2792             Dom.setStyle(el, "height", height);
2793             this.cfg.refireEvent("iframe");
2794     
2795         },
2796         
2797         /**
2798         * The default event handler fired when the "width" property is changed.
2799         * @method configWidth
2800         * @param {String} type The CustomEvent type (usually the property name)
2801         * @param {Object[]} args The CustomEvent arguments. For configuration 
2802         * handlers, args[0] will equal the newly applied value for the property.
2803         * @param {Object} obj The scope object. For configuration handlers, 
2804         * this will usually equal the owner.
2805         */
2806         configWidth: function (type, args, obj) {
2807     
2808             var width = args[0],
2809                 el = this.element;
2810     
2811             Dom.setStyle(el, "width", width);
2812             this.cfg.refireEvent("iframe");
2813     
2814         },
2815         
2816         /**
2817         * The default event handler fired when the "zIndex" property is changed.
2818         * @method configzIndex
2819         * @param {String} type The CustomEvent type (usually the property name)
2820         * @param {Object[]} args The CustomEvent arguments. For configuration 
2821         * handlers, args[0] will equal the newly applied value for the property.
2822         * @param {Object} obj The scope object. For configuration handlers, 
2823         * this will usually equal the owner.
2824         */
2825         configzIndex: function (type, args, obj) {
2826     
2827             var zIndex = args[0],
2828                 el = this.element;
2829         
2830             if (! zIndex) {
2831     
2832                 zIndex = Dom.getStyle(el, "zIndex");
2833         
2834                 if (! zIndex || isNaN(zIndex)) {
2835     
2836                     zIndex = 0;
2837     
2838                 }
2839     
2840             }
2841             
2842             if (this.iframe) {
2843     
2844                 if (zIndex <= 0) {
2845     
2846                     zIndex = 1;
2847     
2848                 }
2849     
2850                 Dom.setStyle(this.iframe, "zIndex", (zIndex - 1));
2851             }
2852             
2853             Dom.setStyle(el, "zIndex", zIndex);
2854             this.cfg.setProperty("zIndex", zIndex, true);
2855     
2856         },
2857         
2858         /**
2859         * The default event handler fired when the "xy" property is changed.
2860         * @method configXY
2861         * @param {String} type The CustomEvent type (usually the property name)
2862         * @param {Object[]} args The CustomEvent arguments. For configuration 
2863         * handlers, args[0] will equal the newly applied value for the property.
2864         * @param {Object} obj The scope object. For configuration handlers, 
2865         * this will usually equal the owner.
2866         */
2867         configXY: function (type, args, obj) {
2868     
2869             var pos = args[0],
2870                 x = pos[0],
2871                 y = pos[1];
2872             
2873             this.cfg.setProperty("x", x);
2874             this.cfg.setProperty("y", y);
2875             
2876             this.beforeMoveEvent.fire([x, y]);
2877             
2878             x = this.cfg.getProperty("x");
2879             y = this.cfg.getProperty("y");
2880             
2881             YAHOO.log(("xy: " + [x, y]), "iframe");
2882             
2883             this.cfg.refireEvent("iframe");
2884             this.moveEvent.fire([x, y]);
2885     
2886         },
2887         
2888         /**
2889         * The default event handler fired when the "x" property is changed.
2890         * @method configX
2891         * @param {String} type The CustomEvent type (usually the property name)
2892         * @param {Object[]} args The CustomEvent arguments. For configuration 
2893         * handlers, args[0] will equal the newly applied value for the property.
2894         * @param {Object} obj The scope object. For configuration handlers, 
2895         * this will usually equal the owner.
2896         */
2897         configX: function (type, args, obj) {
2898     
2899             var x = args[0],
2900                 y = this.cfg.getProperty("y");
2901             
2902             this.cfg.setProperty("x", x, true);
2903             this.cfg.setProperty("y", y, true);
2904             
2905             this.beforeMoveEvent.fire([x, y]);
2906             
2907             x = this.cfg.getProperty("x");
2908             y = this.cfg.getProperty("y");
2909             
2910             Dom.setX(this.element, x, true);
2911             
2912             this.cfg.setProperty("xy", [x, y], true);
2913            
2914             this.cfg.refireEvent("iframe");
2915             this.moveEvent.fire([x, y]);
2916     
2917         },
2918         
2919         /**
2920         * The default event handler fired when the "y" property is changed.
2921         * @method configY
2922         * @param {String} type The CustomEvent type (usually the property name)
2923         * @param {Object[]} args The CustomEvent arguments. For configuration 
2924         * handlers, args[0] will equal the newly applied value for the property.
2925         * @param {Object} obj The scope object. For configuration handlers, 
2926         * this will usually equal the owner.
2927         */
2928         configY: function (type, args, obj) {
2929     
2930             var x = this.cfg.getProperty("x"),
2931                 y = args[0];
2932         
2933             this.cfg.setProperty("x", x, true);
2934             this.cfg.setProperty("y", y, true);
2935             
2936             this.beforeMoveEvent.fire([x, y]);
2937             
2938             x = this.cfg.getProperty("x");
2939             y = this.cfg.getProperty("y");
2940             
2941             Dom.setY(this.element, y, true);
2942             
2943             this.cfg.setProperty("xy", [x, y], true);
2944             
2945             this.cfg.refireEvent("iframe");
2946             this.moveEvent.fire([x, y]);
2947     
2948         },
2949         
2950         /**
2951         * Shows the iframe shim, if it has been enabled.
2952         * @method showIframe
2953         */
2954         showIframe: function () {
2956             var oIFrame = this.iframe,
2957                 oParentNode;
2959             if (oIFrame) {
2960     
2961                 oParentNode = this.element.parentNode;
2963                 if (oParentNode != oIFrame.parentNode) {
2965                     oParentNode.appendChild(oIFrame);
2966                 
2967                 }
2969                 oIFrame.style.display = "block";
2970     
2971             }
2972     
2973         },
2974         
2975         /**
2976         * Hides the iframe shim, if it has been enabled.
2977         * @method hideIframe
2978         */
2979         hideIframe: function () {
2980     
2981             if (this.iframe) {
2982     
2983                 this.iframe.style.display = "none";
2984     
2985             }
2986     
2987         },
2989         /**
2990         * Syncronizes the size and position of iframe shim to that of its 
2991         * corresponding Overlay instance.
2992         * @method syncIframe
2993         */
2994         syncIframe: function () {
2996             var oIFrame = this.iframe,
2997                 oElement = this.element,
2998                 nOffset = Overlay.IFRAME_OFFSET,
2999                 nDimensionOffset = (nOffset * 2),
3000                 aXY;
3003             if (oIFrame) {
3005                 // Size <iframe>
3007                 oIFrame.style.width = 
3008                     (oElement.offsetWidth + nDimensionOffset + "px");
3010                 oIFrame.style.height = 
3011                     (oElement.offsetHeight + nDimensionOffset + "px");
3014                 // Position <iframe>
3016                 aXY = this.cfg.getProperty("xy");
3018                 if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
3020                     this.syncPosition();
3022                     aXY = this.cfg.getProperty("xy");
3024                 }
3026                 Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
3028             }
3029         
3030         },
3032         
3033         /**
3034         * The default event handler fired when the "iframe" property is changed.
3035         * @method configIframe
3036         * @param {String} type The CustomEvent type (usually the property name)
3037         * @param {Object[]} args The CustomEvent arguments. For configuration 
3038         * handlers, args[0] will equal the newly applied value for the property.
3039         * @param {Object} obj The scope object. For configuration handlers, 
3040         * this will usually equal the owner.
3041         */
3042         configIframe: function (type, args, obj) {
3044             var bIFrame = args[0];
3046             function createIFrame() {
3048                 var oIFrame = this.iframe,
3049                     oElement = this.element,
3050                     oParent,
3051                     aXY;
3054                 if (!oIFrame) {
3056                     if (!m_oIFrameTemplate) {
3057     
3058                         m_oIFrameTemplate = document.createElement("iframe");
3060                         if (this.isSecure) {
3061         
3062                             m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
3063         
3064                         }
3066                         /*
3067                             Set the opacity of the <iframe> to 0 so that it 
3068                             doesn't modify the opacity of any transparent 
3069                             elements that may be on top of it (like a shadow).
3070                         */
3071         
3072                         if (YAHOO.env.ua.ie) {
3073         
3074                             m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
3075         
3076                             /*
3077                                  Need to set the "frameBorder" property to 0 
3078                                  supress the default <iframe> border in IE.  
3079                                  Setting the CSS "border" property alone 
3080                                  doesn't supress it.
3081                             */
3082         
3083                             m_oIFrameTemplate.frameBorder = 0;
3084         
3085                         }
3086                         else {
3087         
3088                             m_oIFrameTemplate.style.opacity = "0";
3089                         
3090                         }
3092                         m_oIFrameTemplate.style.position = "absolute";
3093                         m_oIFrameTemplate.style.border = "none";
3094                         m_oIFrameTemplate.style.margin = "0";
3095                         m_oIFrameTemplate.style.padding = "0";
3096                         m_oIFrameTemplate.style.display = "none";
3097     
3098                     }
3100                     oIFrame = m_oIFrameTemplate.cloneNode(false);
3102                     oParent = oElement.parentNode;
3104                     if (oParent) {
3106                         oParent.appendChild(oIFrame);
3108                     } else {
3110                         document.body.appendChild(oIFrame);
3112                     }
3113                     
3114                     this.iframe = oIFrame;
3116                 }
3119                 /*
3120                      Show the <iframe> before positioning it since the "setXY" 
3121                      method of DOM requires the element be in the document 
3122                      and visible.
3123                 */
3125                 this.showIframe();
3128                 /*
3129                      Syncronize the size and position of the <iframe> to that 
3130                      of the Overlay.
3131                 */
3132                 
3133                 this.syncIframe();
3136                 // Add event listeners to update the <iframe> when necessary
3138                 if (!this._hasIframeEventListeners) {
3140                     this.showEvent.subscribe(this.showIframe);
3141                     this.hideEvent.subscribe(this.hideIframe);
3142                     this.changeContentEvent.subscribe(this.syncIframe);
3144                     this._hasIframeEventListeners = true;
3145                     
3146                 }
3147                 
3148             }
3151             function onBeforeShow() {
3152             
3153                 createIFrame.call(this);
3154         
3155                 this.beforeShowEvent.unsubscribe(onBeforeShow);
3156                 
3157                 this._iframeDeferred = false;
3158             
3159             }
3160             
3162             if (bIFrame) { // <iframe> shim is enabled
3163                 
3164                 if (this.cfg.getProperty("visible")) {
3166                     createIFrame.call(this);
3167                 
3168                 }
3169                 else {
3171                     if (!this._iframeDeferred) {
3173                         this.beforeShowEvent.subscribe(onBeforeShow);
3175                         this._iframeDeferred = true;
3176                     
3177                     }
3178                 
3179                 }
3180     
3181             } else {    // <iframe> shim is disabled
3182     
3183                 this.hideIframe();
3185                 if (this._hasIframeEventListeners) {
3187                     this.showEvent.unsubscribe(this.showIframe);
3188                     this.hideEvent.unsubscribe(this.hideIframe);
3189                     this.changeContentEvent.unsubscribe(this.syncIframe);
3191                     this._hasIframeEventListeners = false;
3193                 }
3194                 
3195             }
3196     
3197         },
3198         
3199         
3200         /**
3201         * The default event handler fired when the "constraintoviewport" 
3202         * property is changed.
3203         * @method configConstrainToViewport
3204         * @param {String} type The CustomEvent type (usually the property name)
3205         * @param {Object[]} args The CustomEvent arguments. For configuration 
3206         * handlers, args[0] will equal the newly applied value for 
3207         * the property.
3208         * @param {Object} obj The scope object. For configuration handlers, 
3209         * this will usually equal the owner.
3210         */
3211         configConstrainToViewport: function (type, args, obj) {
3212     
3213             var val = args[0];
3214     
3215             if (val) {
3216     
3217                 if (! Config.alreadySubscribed(this.beforeMoveEvent, 
3218                     this.enforceConstraints, this)) {
3219     
3220                     this.beforeMoveEvent.subscribe(this.enforceConstraints, 
3221                         this, true);
3222     
3223                 }
3224     
3225             } else {
3226     
3227                 this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
3228     
3229             }
3230     
3231         },
3232         
3233         /**
3234         * The default event handler fired when the "context" property 
3235         * is changed.
3236         * @method configContext
3237         * @param {String} type The CustomEvent type (usually the property name)
3238         * @param {Object[]} args The CustomEvent arguments. For configuration 
3239         * handlers, args[0] will equal the newly applied value for the property.
3240         * @param {Object} obj The scope object. For configuration handlers, 
3241         * this will usually equal the owner.
3242         */
3243         configContext: function (type, args, obj) {
3244     
3245             var contextArgs = args[0],
3246                 contextEl,
3247                 elementMagnetCorner,
3248                 contextMagnetCorner;
3249             
3250             if (contextArgs) {
3251             
3252                 contextEl = contextArgs[0];
3253                 elementMagnetCorner = contextArgs[1];
3254                 contextMagnetCorner = contextArgs[2];
3255                 
3256                 if (contextEl) {
3257     
3258                     if (typeof contextEl == "string") {
3259     
3260                         this.cfg.setProperty("context", 
3261                             [document.getElementById(contextEl), 
3262                                 elementMagnetCorner, contextMagnetCorner], 
3263                                 true);
3264     
3265                     }
3266                     
3267                     if (elementMagnetCorner && contextMagnetCorner) {
3268     
3269                         this.align(elementMagnetCorner, contextMagnetCorner);
3270     
3271                     }
3272     
3273                 }
3274     
3275             }
3276     
3277         },
3278         
3279         
3280         // END BUILT-IN PROPERTY EVENT HANDLERS //
3281         
3282         /**
3283         * Aligns the Overlay to its context element using the specified corner 
3284         * points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, 
3285         * and BOTTOM_RIGHT.
3286         * @method align
3287         * @param {String} elementAlign  The String representing the corner of 
3288         * the Overlay that should be aligned to the context element
3289         * @param {String} contextAlign  The corner of the context element 
3290         * that the elementAlign corner should stick to.
3291         */
3292         align: function (elementAlign, contextAlign) {
3293     
3294             var contextArgs = this.cfg.getProperty("context"),
3295                 me = this,
3296                 context,
3297                 element,
3298                 contextRegion;
3299     
3300     
3301             function doAlign(v, h) {
3302     
3303                 switch (elementAlign) {
3304     
3305                 case Overlay.TOP_LEFT:
3306     
3307                     me.moveTo(h, v);
3308     
3309                     break;
3310     
3311                 case Overlay.TOP_RIGHT:
3312     
3313                     me.moveTo((h - element.offsetWidth), v);
3314     
3315                     break;
3316     
3317                 case Overlay.BOTTOM_LEFT:
3318     
3319                     me.moveTo(h, (v - element.offsetHeight));
3320     
3321                     break;
3322     
3323                 case Overlay.BOTTOM_RIGHT:
3324     
3325                     me.moveTo((h - element.offsetWidth), 
3326                         (v - element.offsetHeight));
3327     
3328                     break;
3329     
3330                 }
3331     
3332             }
3333     
3334     
3335             if (contextArgs) {
3336             
3337                 context = contextArgs[0];
3338                 element = this.element;
3339                 me = this;
3340                 
3341                 if (! elementAlign) {
3342     
3343                     elementAlign = contextArgs[1];
3344     
3345                 }
3346                 
3347                 if (! contextAlign) {
3348     
3349                     contextAlign = contextArgs[2];
3350     
3351                 }
3352                 
3353                 if (element && context) {
3354     
3355                     contextRegion = Dom.getRegion(context);
3356                     
3357                     switch (contextAlign) {
3358     
3359                     case Overlay.TOP_LEFT:
3360     
3361                         doAlign(contextRegion.top, contextRegion.left);
3362     
3363                         break;
3364     
3365                     case Overlay.TOP_RIGHT:
3366     
3367                         doAlign(contextRegion.top, contextRegion.right);
3368     
3369                         break;
3370     
3371                     case Overlay.BOTTOM_LEFT:
3372     
3373                         doAlign(contextRegion.bottom, contextRegion.left);
3374     
3375                         break;
3376     
3377                     case Overlay.BOTTOM_RIGHT:
3378     
3379                         doAlign(contextRegion.bottom, contextRegion.right);
3380     
3381                         break;
3382     
3383                     }
3384     
3385                 }
3386     
3387             }
3388             
3389         },
3390         
3391         /**
3392         * The default event handler executed when the moveEvent is fired, if the 
3393         * "constraintoviewport" is set to true.
3394         * @method enforceConstraints
3395         * @param {String} type The CustomEvent type (usually the property name)
3396         * @param {Object[]} args The CustomEvent arguments. For configuration 
3397         * handlers, args[0] will equal the newly applied value for the property.
3398         * @param {Object} obj The scope object. For configuration handlers, 
3399         * this will usually equal the owner.
3400         */
3401         enforceConstraints: function (type, args, obj) {
3402     
3403             var pos = args[0],
3404                 x = pos[0],
3405                 y = pos[1],
3406                 offsetHeight = this.element.offsetHeight,
3407                 offsetWidth = this.element.offsetWidth,
3408                 viewPortWidth = Dom.getViewportWidth(),
3409                 viewPortHeight = Dom.getViewportHeight(),
3410                 scrollX = Dom.getDocumentScrollLeft(),
3411                 scrollY = Dom.getDocumentScrollTop(),
3412                 topConstraint = scrollY + 10,
3413                 leftConstraint = scrollX + 10,
3414                 bottomConstraint = scrollY + viewPortHeight - offsetHeight - 10,
3415                 rightConstraint = scrollX + viewPortWidth - offsetWidth - 10;
3416         
3417     
3418             if (x < leftConstraint) {
3419     
3420                 x = leftConstraint;
3421     
3422             } else if (x > rightConstraint) {
3423     
3424                 x = rightConstraint;
3425     
3426             }
3427             
3428             if (y < topConstraint) {
3429     
3430                 y = topConstraint;
3431     
3432             } else if (y > bottomConstraint) {
3433     
3434                 y = bottomConstraint;
3435     
3436             }
3437             
3438             this.cfg.setProperty("x", x, true);
3439             this.cfg.setProperty("y", y, true);
3440             this.cfg.setProperty("xy", [x, y], true);
3441     
3442         },
3443         
3444         /**
3445         * Centers the container in the viewport.
3446         * @method center
3447         */
3448         center: function () {
3449     
3450             var scrollX = Dom.getDocumentScrollLeft(),
3451                 scrollY = Dom.getDocumentScrollTop(),
3452     
3453                 viewPortWidth = Dom.getClientWidth(),
3454                 viewPortHeight = Dom.getClientHeight(),
3455                 elementWidth = this.element.offsetWidth,
3456                 elementHeight = this.element.offsetHeight,
3457                 x = (viewPortWidth / 2) - (elementWidth / 2) + scrollX,
3458                 y = (viewPortHeight / 2) - (elementHeight / 2) + scrollY;
3459             
3460             this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
3461             
3462             this.cfg.refireEvent("iframe");
3463     
3464         },
3465         
3466         /**
3467         * Synchronizes the Panel's "xy", "x", and "y" properties with the 
3468         * Panel's position in the DOM. This is primarily used to update  
3469         * position information during drag & drop.
3470         * @method syncPosition
3471         */
3472         syncPosition: function () {
3473     
3474             var pos = Dom.getXY(this.element);
3475     
3476             this.cfg.setProperty("x", pos[0], true);
3477             this.cfg.setProperty("y", pos[1], true);
3478             this.cfg.setProperty("xy", pos, true);
3479     
3480         },
3481         
3482         /**
3483         * Event handler fired when the resize monitor element is resized.
3484         * @method onDomResize
3485         * @param {DOMEvent} e The resize DOM event
3486         * @param {Object} obj The scope object
3487         */
3488         onDomResize: function (e, obj) {
3489     
3490             var me = this;
3491     
3492             Overlay.superclass.onDomResize.call(this, e, obj);
3493     
3494             setTimeout(function () {
3495                 me.syncPosition();
3496                 me.cfg.refireEvent("iframe");
3497                 me.cfg.refireEvent("context");
3498             }, 0);
3499     
3500         },
3502         /**
3503         * Places the Overlay on top of all other instances of 
3504         * YAHOO.widget.Overlay.
3505         * @method bringToTop
3506         */
3507         bringToTop: function() {
3508     
3509             var aOverlays = [],
3510                 oElement = this.element;
3511     
3512             function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
3513         
3514                 var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
3515         
3516                     sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
3517         
3518                     nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 
3519                         0 : parseInt(sZIndex1, 10),
3520         
3521                     nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 
3522                         0 : parseInt(sZIndex2, 10);
3523         
3524                 if (nZIndex1 > nZIndex2) {
3525         
3526                     return -1;
3527         
3528                 } else if (nZIndex1 < nZIndex2) {
3529         
3530                     return 1;
3531         
3532                 } else {
3533         
3534                     return 0;
3535         
3536                 }
3537         
3538             }
3539         
3540             function isOverlayElement(p_oElement) {
3541         
3542                 var oOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
3543                     Panel = YAHOO.widget.Panel;
3544             
3545                 if (oOverlay && !Dom.isAncestor(oElement, oOverlay)) {
3546                 
3547                     if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
3548         
3549                         aOverlays[aOverlays.length] = p_oElement.parentNode;
3550                     
3551                     }
3552                     else {
3553         
3554                         aOverlays[aOverlays.length] = p_oElement;
3555         
3556                     }
3557                 
3558                 }
3559             
3560             }
3561             
3562             Dom.getElementsBy(isOverlayElement, "DIV", document.body);
3563     
3564             aOverlays.sort(compareZIndexDesc);
3565             
3566             var oTopOverlay = aOverlays[0],
3567                 nTopZIndex;
3568             
3569             if (oTopOverlay) {
3570     
3571                 nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
3572     
3573                 if (!isNaN(nTopZIndex) && oTopOverlay != oElement) {
3574     
3575                     this.cfg.setProperty("zindex", 
3576                         (parseInt(nTopZIndex, 10) + 2));
3577     
3578                 }
3579             
3580             }
3581         
3582         },
3583         
3584         /**
3585         * Removes the Overlay element from the DOM and sets all child 
3586         * elements to null.
3587         * @method destroy
3588         */
3589         destroy: function () {
3590     
3591             if (this.iframe) {
3592     
3593                 this.iframe.parentNode.removeChild(this.iframe);
3594     
3595             }
3596         
3597             this.iframe = null;
3598         
3599             Overlay.windowResizeEvent.unsubscribe(
3600                 this.doCenterOnDOMEvent, this);
3601     
3602             Overlay.windowScrollEvent.unsubscribe(
3603                 this.doCenterOnDOMEvent, this);
3604         
3605             Overlay.superclass.destroy.call(this);
3606         },
3607         
3608         /**
3609         * Returns a String representation of the object.
3610         * @method toString
3611         * @return {String} The string representation of the Overlay.
3612         */
3613         toString: function () {
3614     
3615             return "Overlay " + this.id;
3616     
3617         }
3618     
3619     });
3620     
3621 }());
3622 (function () {
3623     
3624     /**
3625     * OverlayManager is used for maintaining the focus status of 
3626     * multiple Overlays.
3627     * @namespace YAHOO.widget
3628     * @namespace YAHOO.widget
3629     * @class OverlayManager
3630     * @constructor
3631     * @param {Array} overlays Optional. A collection of Overlays to register 
3632     * with the manager.
3633     * @param {Object} userConfig  The object literal representing the user 
3634     * configuration of the OverlayManager
3635     */
3636     YAHOO.widget.OverlayManager = function (userConfig) {
3637     
3638         this.init(userConfig);
3639     
3640     };
3643     var Overlay = YAHOO.widget.Overlay,
3644         Event = YAHOO.util.Event,
3645         Dom = YAHOO.util.Dom,
3646         Config = YAHOO.util.Config,
3647         CustomEvent = YAHOO.util.CustomEvent,
3648         OverlayManager = YAHOO.widget.OverlayManager;
3650     
3651     /**
3652     * The CSS class representing a focused Overlay
3653     * @property OverlayManager.CSS_FOCUSED
3654     * @static
3655     * @final
3656     * @type String
3657     */
3658     OverlayManager.CSS_FOCUSED = "focused";
3659     
3660     OverlayManager.prototype = {
3661     
3662         /**
3663         * The class's constructor function
3664         * @property contructor
3665         * @type Function
3666         */
3667         constructor: OverlayManager,
3668         
3669         /**
3670         * The array of Overlays that are currently registered
3671         * @property overlays
3672         * @type YAHOO.widget.Overlay[]
3673         */
3674         overlays: null,
3675         
3676         /**
3677         * Initializes the default configuration of the OverlayManager
3678         * @method initDefaultConfig
3679         */
3680         initDefaultConfig: function () {
3681         
3682             /**
3683             * The collection of registered Overlays in use by 
3684             * the OverlayManager
3685             * @config overlays
3686             * @type YAHOO.widget.Overlay[]
3687             * @default null
3688             */
3689             this.cfg.addProperty("overlays", { suppressEvent: true } );
3690         
3691             /**
3692             * The default DOM event that should be used to focus an Overlay
3693             * @config focusevent
3694             * @type String
3695             * @default "mousedown"
3696             */
3697             this.cfg.addProperty("focusevent", { value: "mousedown" } );
3698         
3699         },
3700         
3701         /**
3702         * Initializes the OverlayManager
3703         * @method init
3704         * @param {Overlay[]} overlays Optional. A collection of Overlays to 
3705         * register with the manager.
3706         * @param {Object} userConfig  The object literal representing the user 
3707         * configuration of the OverlayManager
3708         */
3709         init: function (userConfig) {
3711             /**
3712             * The OverlayManager's Config object used for monitoring 
3713             * configuration properties.
3714             * @property cfg
3715             * @type Config
3716             */
3717             this.cfg = new Config(this);
3718         
3719             this.initDefaultConfig();
3720         
3721             if (userConfig) {
3722                 this.cfg.applyConfig(userConfig, true);
3723             }
3724             this.cfg.fireQueue();
3725         
3726             /**
3727             * The currently activated Overlay
3728             * @property activeOverlay
3729             * @private
3730             * @type YAHOO.widget.Overlay
3731             */
3732             var activeOverlay = null;
3733         
3734             /**
3735             * Returns the currently focused Overlay
3736             * @method getActive
3737             * @return {Overlay} The currently focused Overlay
3738             */
3739             this.getActive = function () {
3740                 return activeOverlay;
3741             };
3742         
3743             /**
3744             * Focuses the specified Overlay
3745             * @method focus
3746             * @param {Overlay} overlay The Overlay to focus
3747             * @param {String} overlay The id of the Overlay to focus
3748             */
3749             this.focus = function (overlay) {
3750         
3751                 var o = this.find(overlay);
3752         
3753                 if (o) {
3754         
3755                     if (activeOverlay != o) {
3756         
3757                         if (activeOverlay) {
3758         
3759                             activeOverlay.blur();
3760         
3761                         }
3762         
3763                         this.bringToTop(o);
3764                         
3765                         activeOverlay = o;
3766         
3767                         Dom.addClass(activeOverlay.element, 
3768                             OverlayManager.CSS_FOCUSED);
3770                         o.focusEvent.fire();
3771                         
3772                     }
3773         
3774                 }
3775         
3776             };
3777         
3778             /**
3779             * Removes the specified Overlay from the manager
3780             * @method remove
3781             * @param {Overlay} overlay The Overlay to remove
3782             * @param {String} overlay The id of the Overlay to remove
3783             */
3784             this.remove = function (overlay) {
3785     
3786                 var o = this.find(overlay),
3787                     originalZ;
3788         
3789                 if (o) {
3791                     if (activeOverlay == o) {
3792                     
3793                         activeOverlay = null;
3794                     
3795                     }
3797                     originalZ = Dom.getStyle(o.element, "zIndex");
3799                     o.cfg.setProperty("zIndex", -1000, true);
3801                     this.overlays.sort(this.compareZIndexDesc);
3803                     this.overlays = 
3804                         this.overlays.slice(0, (this.overlays.length - 1));
3805         
3806                     o.hideEvent.unsubscribe(o.blur);
3807                     o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
3808         
3809                     if (o.element) {
3810         
3811                         Event.removeListener(o.element, 
3812                             this.cfg.getProperty("focusevent"), 
3813                             this._onOverlayElementFocus);
3814         
3815                     }
3816         
3817                     o.cfg.setProperty("zIndex", originalZ, true);
3818                     o.cfg.setProperty("manager", null);
3819         
3820                     o.focusEvent.unsubscribeAll();
3821                     o.blurEvent.unsubscribeAll();
3822         
3823                     o.focusEvent = null;
3824                     o.blurEvent = null;
3825         
3826                     o.focus = null;
3827                     o.blur = null;
3828                 }
3830             };
3831         
3832             /**
3833             * Removes focus from all registered Overlays in the manager
3834             * @method blurAll
3835             */
3836             this.blurAll = function () {
3837     
3838                 var nOverlays = this.overlays.length,
3839                     i;
3841                 if (nOverlays > 0) {
3843                     i = nOverlays - 1;
3844                     
3845                     do {
3847                         this.overlays[i].blur();                    
3848                     
3849                     }
3850                     while(i--);
3851                 
3852                 }
3853     
3854             };
3855         
3856         
3857             this._onOverlayBlur = function (p_sType, p_aArgs) {
3859                 activeOverlay = null;
3861             };
3862         
3863         
3864             var overlays = this.cfg.getProperty("overlays");
3865         
3866             if (! this.overlays) {
3867                 this.overlays = [];
3868             }
3869         
3870             if (overlays) {
3871                 this.register(overlays);
3872                 this.overlays.sort(this.compareZIndexDesc);
3873             }
3874         },
3875         
3876         
3877         /**
3878         * @method _onOverlayElementFocus
3879         * @description Event handler for the DOM event that is used to focus 
3880         * the Overlay instance as specified by the "focusevent" 
3881         * configuration property.
3882         * @private
3883         * @param {Event} p_oEvent Object representing the DOM event 
3884         * object passed back by the event utility (Event).
3885         */
3886         _onOverlayElementFocus: function (p_oEvent) {
3887         
3888             var oTarget = Event.getTarget(p_oEvent),
3889                 oClose = this.close;
3890         
3891             
3892             if (oClose && (oTarget == oClose || 
3893                     Dom.isAncestor(oClose, oTarget))) {
3894             
3895                 this.blur();
3896             
3897             }
3898             else {
3899             
3900                 this.focus();
3901             
3902             }
3903         
3904         },
3905         
3906         
3907         /**
3908         * @method _onOverlayDestroy
3909         * @description "destroy" event handler for the Overlay.
3910         * @private
3911         * @param {String} p_sType String representing the name of the event  
3912         * that was fired.
3913         * @param {Array} p_aArgs Array of arguments sent when the event 
3914         * was fired.
3915         * @param {Overlay} p_oOverlay Object representing the menu that 
3916         * fired the event.
3917         */
3918         _onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
3919         
3920             this.remove(p_oOverlay);
3921         
3922         },
3923         
3924         /**
3925         * Registers an Overlay or an array of Overlays with the manager. Upon 
3926         * registration, the Overlay receives functions for focus and blur, 
3927         * along with CustomEvents for each.
3928         * @method register
3929         * @param {Overlay} overlay  An Overlay to register with the manager.
3930         * @param {Overlay[]} overlay  An array of Overlays to register with 
3931         * the manager.
3932         * @return {Boolean} True if any Overlays are registered.
3933         */
3934         register: function (overlay) {
3935         
3936             var mgr = this,
3937                 zIndex,
3938                 regcount,
3939                 i,
3940                 nOverlays;
3941         
3942             if (overlay instanceof Overlay) {
3944                 overlay.cfg.addProperty("manager", { value: this } );
3945         
3946                 overlay.focusEvent = overlay.createEvent("focus");
3947                 overlay.focusEvent.signature = CustomEvent.LIST;
3948         
3949                 overlay.blurEvent = overlay.createEvent("blur");
3950                 overlay.blurEvent.signature = CustomEvent.LIST;
3951         
3952                 overlay.focus = function () {
3953                     mgr.focus(this);
3954                 };
3955         
3956                 overlay.blur = function () {
3957     
3958                     if (mgr.getActive() == this) {
3960                         Dom.removeClass(this.element, 
3961                             OverlayManager.CSS_FOCUSED);
3963                         this.blurEvent.fire();
3965                     }
3967                 };
3968         
3969                 overlay.blurEvent.subscribe(mgr._onOverlayBlur);
3970         
3971                 overlay.hideEvent.subscribe(overlay.blur);
3972                 
3973                 overlay.destroyEvent.subscribe(this._onOverlayDestroy, 
3974                     overlay, this);
3975         
3976                 Event.on(overlay.element, this.cfg.getProperty("focusevent"), 
3977                     this._onOverlayElementFocus, null, overlay);
3978         
3979                 zIndex = Dom.getStyle(overlay.element, "zIndex");
3981                 if (!isNaN(zIndex)) {
3983                     overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
3985                 } else {
3987                     overlay.cfg.setProperty("zIndex", 0);
3989                 }
3990         
3992                 this.overlays.push(overlay);
3994                 this.bringToTop(overlay);
3996                 return true;
3998             } else if (overlay instanceof Array) {
4000                 regcount = 0;
4001                 nOverlays = overlay.length;
4003                 for (i = 0; i < nOverlays; i++) {
4005                     if (this.register(overlay[i])) {
4007                         regcount++;
4009                     }
4010                 }
4012                 if (regcount > 0) {
4014                     return true;
4016                 }
4018             } else {
4020                 return false;
4022             }
4024         },
4026         /**
4027         * Places the specified Overlay instance on top of all other 
4028         * Overlay instances.
4029         * @method bringToTop
4030         * @param {YAHOO.widget.Overlay} p_oOverlay Object representing an 
4031         * Overlay instance.
4032         * @param {String} p_oOverlay String representing the id of an 
4033         * Overlay instance.
4034         */        
4035         bringToTop: function (p_oOverlay) {
4037             var oOverlay = this.find(p_oOverlay),
4038                 nTopZIndex,
4039                 oTopOverlay,
4040                 aOverlays;
4042             if (oOverlay) {
4044                 aOverlays = this.overlays;
4046                 aOverlays.sort(this.compareZIndexDesc);
4047                 
4048                 oTopOverlay = aOverlays[0];
4049                 
4050                 if (oTopOverlay) {
4052                     nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
4053     
4054                     if (!isNaN(nTopZIndex) && oTopOverlay != oOverlay) {
4055     
4056                         oOverlay.cfg.setProperty("zIndex", 
4057                             (parseInt(nTopZIndex, 10) + 2));
4058     
4059                     }
4060     
4061                     aOverlays.sort(this.compareZIndexDesc);
4062                 
4063                 }
4065             }
4066         
4067         },
4068         
4069         /**
4070         * Attempts to locate an Overlay by instance or ID.
4071         * @method find
4072         * @param {Overlay} overlay  An Overlay to locate within the manager
4073         * @param {String} overlay  An Overlay id to locate within the manager
4074         * @return {Overlay} The requested Overlay, if found, or null if it 
4075         * cannot be located.
4076         */
4077         find: function (overlay) {
4078         
4079             var aOverlays = this.overlays,
4080                 nOverlays = aOverlays.length,
4081                 i;
4083             if (nOverlays > 0) {
4085                 i = nOverlays - 1;
4087                 if (overlay instanceof Overlay) {
4089                     do {
4091                         if (aOverlays[i] == overlay) {
4093                             return aOverlays[i];
4095                         }
4096                     
4097                     }
4098                     while(i--);
4100                 } else if (typeof overlay == "string") {
4102                     do {
4104                         if (aOverlays[i].id == overlay) {
4106                             return aOverlays[i];
4108                         }
4110                     }
4111                     while(i--);
4113                 }
4115                 return null;
4116             
4117             }
4119         },
4120         
4121         /**
4122         * Used for sorting the manager's Overlays by z-index.
4123         * @method compareZIndexDesc
4124         * @private
4125         * @return {Number} 0, 1, or -1, depending on where the Overlay should 
4126         * fall in the stacking order.
4127         */
4128         compareZIndexDesc: function (o1, o2) {
4129     
4130             var zIndex1 = o1.cfg.getProperty("zIndex"),
4131                 zIndex2 = o2.cfg.getProperty("zIndex");
4132         
4133             if (zIndex1 > zIndex2) {
4134                 return -1;
4135             } else if (zIndex1 < zIndex2) {
4136                 return 1;
4137             } else {
4138                 return 0;
4139             }
4140         },
4141         
4142         /**
4143         * Shows all Overlays in the manager.
4144         * @method showAll
4145         */
4146         showAll: function () {
4147         
4148             var aOverlays = this.overlays,
4149                 nOverlays = aOverlays.length,
4150                 i;
4152             if (nOverlays > 0) {
4153             
4154                 i = nOverlays - 1;
4155                 
4156                 do {
4158                     aOverlays[i].show();
4159                 
4160                 }
4161                 while(i--);
4162             
4163             }
4164     
4165         },
4166         
4167         /**
4168         * Hides all Overlays in the manager.
4169         * @method hideAll
4170         */
4171         hideAll: function () {
4172         
4173             var aOverlays = this.overlays,
4174                 nOverlays = aOverlays.length,
4175                 i;
4177             if (nOverlays > 0) {
4178             
4179                 i = nOverlays - 1;
4180                 
4181                 do {
4183                     aOverlays[i].hide();
4184                 
4185                 }
4186                 while(i--);
4187             
4188             }
4189     
4190         },
4191         
4192         /**
4193         * Returns a string representation of the object.
4194         * @method toString
4195         * @return {String} The string representation of the OverlayManager
4196         */
4197         toString: function () {
4198             return "OverlayManager";
4199         }
4200     
4201     };
4203 }());
4204 (function () {
4206     /**
4207     * ContainerEffect encapsulates animation transitions that are executed when 
4208     * an Overlay is shown or hidden.
4209     * @namespace YAHOO.widget
4210     * @class ContainerEffect
4211     * @constructor
4212     * @param {YAHOO.widget.Overlay} overlay The Overlay that the animation 
4213     * should be associated with
4214     * @param {Object} attrIn The object literal representing the animation 
4215     * arguments to be used for the animate-in transition. The arguments for 
4216     * this literal are: attributes(object, see YAHOO.util.Anim for description), 
4217     * duration(Number), and method(i.e. Easing.easeIn).
4218     * @param {Object} attrOut The object literal representing the animation 
4219     * arguments to be used for the animate-out transition. The arguments for  
4220     * this literal are: attributes(object, see YAHOO.util.Anim for description), 
4221     * duration(Number), and method(i.e. Easing.easeIn).
4222     * @param {HTMLElement} targetElement Optional. The target element that  
4223     * should be animated during the transition. Defaults to overlay.element.
4224     * @param {class} Optional. The animation class to instantiate. Defaults to 
4225     * YAHOO.util.Anim. Other options include YAHOO.util.Motion.
4226     */
4227     YAHOO.widget.ContainerEffect = 
4228     
4229         function (overlay, attrIn, attrOut, targetElement, animClass) {
4230     
4231         if (!animClass) {
4232             animClass = YAHOO.util.Anim;
4233         }
4234         
4235         /**
4236         * The overlay to animate
4237         * @property overlay
4238         * @type YAHOO.widget.Overlay
4239         */
4240         this.overlay = overlay;
4241     
4242         /**
4243         * The animation attributes to use when transitioning into view
4244         * @property attrIn
4245         * @type Object
4246         */
4247         this.attrIn = attrIn;
4248     
4249         /**
4250         * The animation attributes to use when transitioning out of view
4251         * @property attrOut
4252         * @type Object
4253         */
4254         this.attrOut = attrOut;
4255     
4256         /**
4257         * The target element to be animated
4258         * @property targetElement
4259         * @type HTMLElement
4260         */
4261         this.targetElement = targetElement || overlay.element;
4262     
4263         /**
4264         * The animation class to use for animating the overlay
4265         * @property animClass
4266         * @type class
4267         */
4268         this.animClass = animClass;
4269     
4270     };
4273     var Dom = YAHOO.util.Dom,
4274         CustomEvent = YAHOO.util.CustomEvent,
4275         Easing = YAHOO.util.Easing,
4276         ContainerEffect = YAHOO.widget.ContainerEffect;
4279     /**
4280     * A pre-configured ContainerEffect instance that can be used for fading 
4281     * an overlay in and out.
4282     * @method FADE
4283     * @static
4284     * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
4285     * @param {Number} dur The duration of the animation
4286     * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
4287     */
4288     ContainerEffect.FADE = function (overlay, dur) {
4289     
4290         var fade = new ContainerEffect(overlay, 
4291         
4292             { attributes: { opacity: { from: 0, to: 1 } }, 
4293                 duration: dur, 
4294                 method: Easing.easeIn }, 
4295             
4296             { attributes: { opacity: { to: 0 } },
4297                 duration: dur, 
4298                 method: Easing.easeOut }, 
4299             
4300             overlay.element);
4301         
4302     
4303         fade.handleStartAnimateIn = function (type,args,obj) {
4304             Dom.addClass(obj.overlay.element, "hide-select");
4305         
4306             if (! obj.overlay.underlay) {
4307                 obj.overlay.cfg.refireEvent("underlay");
4308             }
4309         
4310             if (obj.overlay.underlay) {
4311     
4312                 obj.initialUnderlayOpacity = 
4313                     Dom.getStyle(obj.overlay.underlay, "opacity");
4314     
4315                 obj.overlay.underlay.style.filter = null;
4316     
4317             }
4318         
4319             Dom.setStyle(obj.overlay.element, "visibility", "visible");
4320             Dom.setStyle(obj.overlay.element, "opacity", 0);
4321         };
4322         
4323     
4324         fade.handleCompleteAnimateIn = function (type,args,obj) {
4325             Dom.removeClass(obj.overlay.element, "hide-select");
4326         
4327             if (obj.overlay.element.style.filter) {
4328                 obj.overlay.element.style.filter = null;
4329             }
4330         
4331             if (obj.overlay.underlay) {
4332                 Dom.setStyle(obj.overlay.underlay, "opacity", 
4333                     obj.initialUnderlayOpacity);
4334             }
4335         
4336             obj.overlay.cfg.refireEvent("iframe");
4337             obj.animateInCompleteEvent.fire();
4338         };
4339         
4340     
4341         fade.handleStartAnimateOut = function (type, args, obj) {
4342             Dom.addClass(obj.overlay.element, "hide-select");
4343         
4344             if (obj.overlay.underlay) {
4345                 obj.overlay.underlay.style.filter = null;
4346             }
4347         };
4348         
4349     
4350         fade.handleCompleteAnimateOut =  function (type, args, obj) {
4351             Dom.removeClass(obj.overlay.element, "hide-select");
4352             if (obj.overlay.element.style.filter) {
4353                 obj.overlay.element.style.filter = null;
4354             }
4355             Dom.setStyle(obj.overlay.element, "visibility", "hidden");
4356             Dom.setStyle(obj.overlay.element, "opacity", 1);
4357         
4358             obj.overlay.cfg.refireEvent("iframe");
4359         
4360             obj.animateOutCompleteEvent.fire();
4361         };
4362         
4363         fade.init();
4364         return fade;
4365     };
4366     
4367     
4368     /**
4369     * A pre-configured ContainerEffect instance that can be used for sliding an 
4370     * overlay in and out.
4371     * @method SLIDE
4372     * @static
4373     * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
4374     * @param {Number} dur The duration of the animation
4375     * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
4376     */
4377     ContainerEffect.SLIDE = function (overlay, dur) {
4378     
4379         var x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
4380     
4381             y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
4382     
4383             clientWidth = Dom.getClientWidth(),
4384     
4385             offsetWidth = overlay.element.offsetWidth,
4386     
4387             slide = new ContainerEffect(overlay, 
4388             
4389             { attributes: { points: { to: [x, y] } },
4390                 duration: dur,
4391                 method: Easing.easeIn },
4392     
4393             { attributes: { points: { to: [(clientWidth + 25), y] } },
4394                 duration: dur,
4395                 method: Easing.easeOut },
4396     
4397             overlay.element, YAHOO.util.Motion);
4398         
4399         
4400         slide.handleStartAnimateIn = function (type,args,obj) {
4401             obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
4402             obj.overlay.element.style.top  = y + "px";
4403         };
4404         
4405         slide.handleTweenAnimateIn = function (type, args, obj) {
4406         
4407             var pos = Dom.getXY(obj.overlay.element),
4408                 currentX = pos[0],
4409                 currentY = pos[1];
4410         
4411             if (Dom.getStyle(obj.overlay.element, "visibility") == 
4412                 "hidden" && currentX < x) {
4414                 Dom.setStyle(obj.overlay.element, "visibility", "visible");
4416             }
4417         
4418             obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
4419             obj.overlay.cfg.refireEvent("iframe");
4420         };
4421         
4422         slide.handleCompleteAnimateIn = function (type, args, obj) {
4423             obj.overlay.cfg.setProperty("xy", [x, y], true);
4424             obj.startX = x;
4425             obj.startY = y;
4426             obj.overlay.cfg.refireEvent("iframe");
4427             obj.animateInCompleteEvent.fire();
4428         };
4429         
4430         slide.handleStartAnimateOut = function (type, args, obj) {
4431     
4432             var vw = Dom.getViewportWidth(),
4433                 pos = Dom.getXY(obj.overlay.element),
4434                 yso = pos[1],
4435                 currentTo = obj.animOut.attributes.points.to;
4436     
4437             obj.animOut.attributes.points.to = [(vw + 25), yso];
4438     
4439         };
4440         
4441         slide.handleTweenAnimateOut = function (type, args, obj) {
4442     
4443             var pos = Dom.getXY(obj.overlay.element),
4444                 xto = pos[0],
4445                 yto = pos[1];
4446         
4447             obj.overlay.cfg.setProperty("xy", [xto, yto], true);
4448             obj.overlay.cfg.refireEvent("iframe");
4449         };
4450         
4451         slide.handleCompleteAnimateOut = function (type, args, obj) {
4452             Dom.setStyle(obj.overlay.element, "visibility", "hidden");
4453         
4454             obj.overlay.cfg.setProperty("xy", [x, y]);
4455             obj.animateOutCompleteEvent.fire();
4456         };
4457         
4458         slide.init();
4459         return slide;
4460     };
4461     
4462     ContainerEffect.prototype = {
4463     
4464         /**
4465         * Initializes the animation classes and events.
4466         * @method init
4467         */
4468         init: function () {
4470             this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
4471             this.beforeAnimateInEvent.signature = CustomEvent.LIST;
4472             
4473             this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
4474             this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
4475         
4476             this.animateInCompleteEvent = this.createEvent("animateInComplete");
4477             this.animateInCompleteEvent.signature = CustomEvent.LIST;
4478         
4479             this.animateOutCompleteEvent = 
4480                 this.createEvent("animateOutComplete");
4481             this.animateOutCompleteEvent.signature = CustomEvent.LIST;
4482         
4483             this.animIn = new this.animClass(this.targetElement, 
4484                 this.attrIn.attributes, this.attrIn.duration, 
4485                 this.attrIn.method);
4487             this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
4488             this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
4490             this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn, 
4491                 this);
4492         
4493             this.animOut = new this.animClass(this.targetElement, 
4494                 this.attrOut.attributes, this.attrOut.duration, 
4495                 this.attrOut.method);
4497             this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
4498             this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
4499             this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut, 
4500                 this);
4502         },
4503         
4504         /**
4505         * Triggers the in-animation.
4506         * @method animateIn
4507         */
4508         animateIn: function () {
4509             this.beforeAnimateInEvent.fire();
4510             this.animIn.animate();
4511         },
4512         
4513         /**
4514         * Triggers the out-animation.
4515         * @method animateOut
4516         */
4517         animateOut: function () {
4518             this.beforeAnimateOutEvent.fire();
4519             this.animOut.animate();
4520         },
4521         
4522         /**
4523         * The default onStart handler for the in-animation.
4524         * @method handleStartAnimateIn
4525         * @param {String} type The CustomEvent type
4526         * @param {Object[]} args The CustomEvent arguments
4527         * @param {Object} obj The scope object
4528         */
4529         handleStartAnimateIn: function (type, args, obj) { },
4530     
4531         /**
4532         * The default onTween handler for the in-animation.
4533         * @method handleTweenAnimateIn
4534         * @param {String} type The CustomEvent type
4535         * @param {Object[]} args The CustomEvent arguments
4536         * @param {Object} obj The scope object
4537         */
4538         handleTweenAnimateIn: function (type, args, obj) { },
4539     
4540         /**
4541         * The default onComplete handler for the in-animation.
4542         * @method handleCompleteAnimateIn
4543         * @param {String} type The CustomEvent type
4544         * @param {Object[]} args The CustomEvent arguments
4545         * @param {Object} obj The scope object
4546         */
4547         handleCompleteAnimateIn: function (type, args, obj) { },
4548         
4549         /**
4550         * The default onStart handler for the out-animation.
4551         * @method handleStartAnimateOut
4552         * @param {String} type The CustomEvent type
4553         * @param {Object[]} args The CustomEvent arguments
4554         * @param {Object} obj The scope object
4555         */
4556         handleStartAnimateOut: function (type, args, obj) { },
4557     
4558         /**
4559         * The default onTween handler for the out-animation.
4560         * @method handleTweenAnimateOut
4561         * @param {String} type The CustomEvent type
4562         * @param {Object[]} args The CustomEvent arguments
4563         * @param {Object} obj The scope object
4564         */
4565         handleTweenAnimateOut: function (type, args, obj) { },
4566     
4567         /**
4568         * The default onComplete handler for the out-animation.
4569         * @method handleCompleteAnimateOut
4570         * @param {String} type The CustomEvent type
4571         * @param {Object[]} args The CustomEvent arguments
4572         * @param {Object} obj The scope object
4573         */
4574         handleCompleteAnimateOut: function (type, args, obj) { },
4575         
4576         /**
4577         * Returns a string representation of the object.
4578         * @method toString
4579         * @return {String} The string representation of the ContainerEffect
4580         */
4581         toString: function () {
4582             var output = "ContainerEffect";
4583             if (this.overlay) {
4584                 output += " [" + this.overlay.toString() + "]";
4585             }
4586             return output;
4587         }
4588     
4589     };
4591     YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
4593 })();
4594 YAHOO.register("container_core", YAHOO.widget.Module, {version: "2.3.0", build: "442"});