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