MDL-11517 reserved word MOD used in table alias in questions backup code
[moodle-pu.git] / lib / yui / container / container-debug.js
blob97b029927731bdd39d04ab5872b0a218f1515756
1 /*
2 Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 2.3.0
6 */
7 (function () {
9     /**
10     * Config is a utility used within an Object to allow the implementer to
11     * maintain a list of local configuration properties and listen for changes 
12     * to those properties dynamically using CustomEvent. The initial values are 
13     * also maintained so that the configuration can be reset at any given point 
14     * to its initial state.
15     * @namespace YAHOO.util
16     * @class Config
17     * @constructor
18     * @param {Object} owner The owner Object to which this Config Object belongs
19     */
20     YAHOO.util.Config = function (owner) {
21     
22         if (owner) {
23     
24             this.init(owner);
25     
26         }
27     
28         if (!owner) { 
29         
30             YAHOO.log("No owner specified for Config object", "error"); 
31     
32         }
33     
34     };
37     var Lang = YAHOO.lang,
38         CustomEvent = YAHOO.util.CustomEvent,        
39         Config = YAHOO.util.Config;
40     
42     /**
43      * Constant representing the CustomEvent type for the config changed event.
44      * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
45      * @private
46      * @static
47      * @final
48      */
49     Config.CONFIG_CHANGED_EVENT = "configChanged";
50     
51     /**
52      * Constant representing the boolean type string
53      * @property YAHOO.util.Config.BOOLEAN_TYPE
54      * @private
55      * @static
56      * @final
57      */
58     Config.BOOLEAN_TYPE = "boolean";
59     
60     Config.prototype = {
61      
62         /**
63         * Object reference to the owner of this Config Object
64         * @property owner
65         * @type Object
66         */
67         owner: null,
68         
69         /**
70         * Boolean flag that specifies whether a queue is currently 
71         * being executed
72         * @property queueInProgress
73         * @type Boolean
74         */
75         queueInProgress: false,
76         
77         /**
78         * Maintains the local collection of configuration property objects and 
79         * their specified values
80         * @property config
81         * @private
82         * @type Object
83         */ 
84         config: null,
85         
86         /**
87         * Maintains the local collection of configuration property objects as 
88         * they were initially applied.
89         * This object is used when resetting a property.
90         * @property initialConfig
91         * @private
92         * @type Object
93         */ 
94         initialConfig: null,
95         
96         /**
97         * Maintains the local, normalized CustomEvent queue
98         * @property eventQueue
99         * @private
100         * @type Object
101         */ 
102         eventQueue: null,
103         
104         /**
105         * Custom Event, notifying subscribers when Config properties are set 
106         * (setProperty is called without the silent flag
107         * @event configChangedEvent
108         */
109         configChangedEvent: null,
110     
111         /**
112         * Initializes the configuration Object and all of its local members.
113         * @method init
114         * @param {Object} owner The owner Object to which this Config 
115         * Object belongs
116         */
117         init: function (owner) {
118     
119             this.owner = owner;
120     
121             this.configChangedEvent = 
122                 this.createEvent(Config.CONFIG_CHANGED_EVENT);
123     
124             this.configChangedEvent.signature = CustomEvent.LIST;
125             this.queueInProgress = false;
126             this.config = {};
127             this.initialConfig = {};
128             this.eventQueue = [];
129         
130         },
131         
132         /**
133         * Validates that the value passed in is a Boolean.
134         * @method checkBoolean
135         * @param {Object} val The value to validate
136         * @return {Boolean} true, if the value is valid
137         */ 
138         checkBoolean: function (val) {
139             return (typeof val == Config.BOOLEAN_TYPE);
140         },
141         
142         /**
143         * Validates that the value passed in is a number.
144         * @method checkNumber
145         * @param {Object} val The value to validate
146         * @return {Boolean} true, if the value is valid
147         */
148         checkNumber: function (val) {
149             return (!isNaN(val));
150         },
151         
152         /**
153         * Fires a configuration property event using the specified value. 
154         * @method fireEvent
155         * @private
156         * @param {String} key The configuration property's name
157         * @param {value} Object The value of the correct type for the property
158         */ 
159         fireEvent: function ( key, value ) {
160             YAHOO.log("Firing Config event: " + key + "=" + value, "info");
161             var property = this.config[key];
162         
163             if (property && property.event) {
164                 property.event.fire(value);
165             } 
166         },
167         
168         /**
169         * Adds a property to the Config Object's private config hash.
170         * @method addProperty
171         * @param {String} key The configuration property's name
172         * @param {Object} propertyObject The Object containing all of this 
173         * property's arguments
174         */
175         addProperty: function ( key, propertyObject ) {
176             key = key.toLowerCase();
177             YAHOO.log("Added property: " + key, "info");
178         
179             this.config[key] = propertyObject;
180         
181             propertyObject.event = this.createEvent(key, { scope: this.owner });
182             propertyObject.event.signature = CustomEvent.LIST;
183             
184             
185             propertyObject.key = key;
186         
187             if (propertyObject.handler) {
188                 propertyObject.event.subscribe(propertyObject.handler, 
189                     this.owner);
190             }
191         
192             this.setProperty(key, propertyObject.value, true);
193             
194             if (! propertyObject.suppressEvent) {
195                 this.queueProperty(key, propertyObject.value);
196             }
197             
198         },
199         
200         /**
201         * Returns a key-value configuration map of the values currently set in  
202         * the Config Object.
203         * @method getConfig
204         * @return {Object} The current config, represented in a key-value map
205         */
206         getConfig: function () {
207         
208             var cfg = {},
209                 prop,
210                 property;
211                 
212             for (prop in this.config) {
213                 property = this.config[prop];
214                 if (property && property.event) {
215                     cfg[prop] = property.value;
216                 }
217             }
218             
219             return cfg;
220         },
221         
222         /**
223         * Returns the value of specified property.
224         * @method getProperty
225         * @param {String} key The name of the property
226         * @return {Object}  The value of the specified property
227         */
228         getProperty: function (key) {
229             var property = this.config[key.toLowerCase()];
230             if (property && property.event) {
231                 return property.value;
232             } else {
233                 return undefined;
234             }
235         },
236         
237         /**
238         * Resets the specified property's value to its initial value.
239         * @method resetProperty
240         * @param {String} key The name of the property
241         * @return {Boolean} True is the property was reset, false if not
242         */
243         resetProperty: function (key) {
244     
245             key = key.toLowerCase();
246         
247             var property = this.config[key];
248     
249             if (property && property.event) {
250     
251                 if (this.initialConfig[key] && 
252                     !Lang.isUndefined(this.initialConfig[key])) {
253     
254                     this.setProperty(key, this.initialConfig[key]);
256                     return true;
257     
258                 }
259     
260             } else {
261     
262                 return false;
263             }
264     
265         },
266         
267         /**
268         * Sets the value of a property. If the silent property is passed as 
269         * true, the property's event will not be fired.
270         * @method setProperty
271         * @param {String} key The name of the property
272         * @param {String} value The value to set the property to
273         * @param {Boolean} silent Whether the value should be set silently, 
274         * without firing the property event.
275         * @return {Boolean} True, if the set was successful, false if it failed.
276         */
277         setProperty: function (key, value, silent) {
278         
279             var property;
280         
281             key = key.toLowerCase();
282             YAHOO.log("setProperty: " + key + "=" + value, "info");
283         
284             if (this.queueInProgress && ! silent) {
285                 // Currently running through a queue... 
286                 this.queueProperty(key,value);
287                 return true;
288     
289             } else {
290                 property = this.config[key];
291                 if (property && property.event) {
292                     if (property.validator && !property.validator(value)) {
293                         return false;
294                     } else {
295                         property.value = value;
296                         if (! silent) {
297                             this.fireEvent(key, value);
298                             this.configChangedEvent.fire([key, value]);
299                         }
300                         return true;
301                     }
302                 } else {
303                     return false;
304                 }
305             }
306         },
307         
308         /**
309         * Sets the value of a property and queues its event to execute. If the 
310         * event is already scheduled to execute, it is
311         * moved from its current position to the end of the queue.
312         * @method queueProperty
313         * @param {String} key The name of the property
314         * @param {String} value The value to set the property to
315         * @return {Boolean}  true, if the set was successful, false if 
316         * it failed.
317         */ 
318         queueProperty: function (key, value) {
319         
320             key = key.toLowerCase();
321             YAHOO.log("queueProperty: " + key + "=" + value, "info");
322         
323             var property = this.config[key],
324                 foundDuplicate = false,
325                 iLen,
326                 queueItem,
327                 queueItemKey,
328                 queueItemValue,
329                 sLen,
330                 supercedesCheck,
331                 qLen,
332                 queueItemCheck,
333                 queueItemCheckKey,
334                 queueItemCheckValue,
335                 i,
336                 s,
337                 q;
338                                 
339             if (property && property.event) {
340     
341                 if (!Lang.isUndefined(value) && property.validator && 
342                     !property.validator(value)) { // validator
343                     return false;
344                 } else {
345         
346                     if (!Lang.isUndefined(value)) {
347                         property.value = value;
348                     } else {
349                         value = property.value;
350                     }
351         
352                     foundDuplicate = false;
353                     iLen = this.eventQueue.length;
354         
355                     for (i = 0; i < iLen; i++) {
356                         queueItem = this.eventQueue[i];
357         
358                         if (queueItem) {
359                             queueItemKey = queueItem[0];
360                             queueItemValue = queueItem[1];
361                             
362                             if (queueItemKey == key) {
363     
364                                 /*
365                                     found a dupe... push to end of queue, null 
366                                     current item, and break
367                                 */
368     
369                                 this.eventQueue[i] = null;
370     
371                                 this.eventQueue.push(
372                                     [key, (!Lang.isUndefined(value) ? 
373                                     value : queueItemValue)]);
374     
375                                 foundDuplicate = true;
376                                 break;
377                             }
378                         }
379                     }
380                     
381                     // this is a refire, or a new property in the queue
382     
383                     if (! foundDuplicate && !Lang.isUndefined(value)) { 
384                         this.eventQueue.push([key, value]);
385                     }
386                 }
387         
388                 if (property.supercedes) {
389         
390                     sLen = property.supercedes.length;
391         
392                     for (s = 0; s < sLen; s++) {
393         
394                         supercedesCheck = property.supercedes[s];
395                         qLen = this.eventQueue.length;
396         
397                         for (q = 0; q < qLen; q++) {
398                             queueItemCheck = this.eventQueue[q];
399         
400                             if (queueItemCheck) {
401                                 queueItemCheckKey = queueItemCheck[0];
402                                 queueItemCheckValue = queueItemCheck[1];
403                                 
404                                 if (queueItemCheckKey == 
405                                     supercedesCheck.toLowerCase() ) {
406     
407                                     this.eventQueue.push([queueItemCheckKey, 
408                                         queueItemCheckValue]);
409     
410                                     this.eventQueue[q] = null;
411                                     break;
412     
413                                 }
414                             }
415                         }
416                     }
417                 }
419                 YAHOO.log("Config event queue: " + this.outputEventQueue(), "info");
420         
421                 return true;
422             } else {
423                 return false;
424             }
425         },
426         
427         /**
428         * Fires the event for a property using the property's current value.
429         * @method refireEvent
430         * @param {String} key The name of the property
431         */
432         refireEvent: function (key) {
433     
434             key = key.toLowerCase();
435         
436             var property = this.config[key];
437     
438             if (property && property.event && 
439     
440                 !Lang.isUndefined(property.value)) {
441     
442                 if (this.queueInProgress) {
443     
444                     this.queueProperty(key);
445     
446                 } else {
447     
448                     this.fireEvent(key, property.value);
449     
450                 }
451     
452             }
453         },
454         
455         /**
456         * Applies a key-value Object literal to the configuration, replacing  
457         * any existing values, and queueing the property events.
458         * Although the values will be set, fireQueue() must be called for their 
459         * associated events to execute.
460         * @method applyConfig
461         * @param {Object} userConfig The configuration Object literal
462         * @param {Boolean} init  When set to true, the initialConfig will 
463         * be set to the userConfig passed in, so that calling a reset will 
464         * reset the properties to the passed values.
465         */
466         applyConfig: function (userConfig, init) {
467         
468             var sKey,
469                 oValue,
470                 oConfig;
472             if (init) {
474                 oConfig = {};
476                 for (sKey in userConfig) {
477                 
478                     if (Lang.hasOwnProperty(userConfig, sKey)) {
480                         oConfig[sKey.toLowerCase()] = userConfig[sKey];
482                     }
483                 
484                 }
486                 this.initialConfig = oConfig;
488             }
490             for (sKey in userConfig) {
491             
492                 if (Lang.hasOwnProperty(userConfig, sKey)) {
493             
494                     this.queueProperty(sKey, userConfig[sKey]);
495                 
496                 }
498             }
500         },
501         
502         /**
503         * Refires the events for all configuration properties using their 
504         * current values.
505         * @method refresh
506         */
507         refresh: function () {
508         
509             var prop;
510         
511             for (prop in this.config) {
512                 this.refireEvent(prop);
513             }
514         },
515         
516         /**
517         * Fires the normalized list of queued property change events
518         * @method fireQueue
519         */
520         fireQueue: function () {
521         
522             var i, 
523                 queueItem,
524                 key,
525                 value,
526                 property;
527         
528             this.queueInProgress = true;
529             for (i = 0;i < this.eventQueue.length; i++) {
530                 queueItem = this.eventQueue[i];
531                 if (queueItem) {
532         
533                     key = queueItem[0];
534                     value = queueItem[1];
535                     property = this.config[key];
536         
537                     property.value = value;
538         
539                     this.fireEvent(key,value);
540                 }
541             }
542             
543             this.queueInProgress = false;
544             this.eventQueue = [];
545         },
546         
547         /**
548         * Subscribes an external handler to the change event for any 
549         * given property. 
550         * @method subscribeToConfigEvent
551         * @param {String} key The property name
552         * @param {Function} handler The handler function to use subscribe to 
553         * the property's event
554         * @param {Object} obj The Object to use for scoping the event handler 
555         * (see CustomEvent documentation)
556         * @param {Boolean} override Optional. If true, will override "this"  
557         * within the handler to map to the scope Object passed into the method.
558         * @return {Boolean} True, if the subscription was successful, 
559         * otherwise false.
560         */ 
561         subscribeToConfigEvent: function (key, handler, obj, override) {
562     
563             var property = this.config[key.toLowerCase()];
564     
565             if (property && property.event) {
566     
567                 if (!Config.alreadySubscribed(property.event, handler, obj)) {
568     
569                     property.event.subscribe(handler, obj, override);
570     
571                 }
572     
573                 return true;
574     
575             } else {
576     
577                 return false;
578     
579             }
580     
581         },
582         
583         /**
584         * Unsubscribes an external handler from the change event for any 
585         * given property. 
586         * @method unsubscribeFromConfigEvent
587         * @param {String} key The property name
588         * @param {Function} handler The handler function to use subscribe to 
589         * the property's event
590         * @param {Object} obj The Object to use for scoping the event 
591         * handler (see CustomEvent documentation)
592         * @return {Boolean} True, if the unsubscription was successful, 
593         * otherwise false.
594         */
595         unsubscribeFromConfigEvent: function (key, handler, obj) {
596             var property = this.config[key.toLowerCase()];
597             if (property && property.event) {
598                 return property.event.unsubscribe(handler, obj);
599             } else {
600                 return false;
601             }
602         },
603         
604         /**
605         * Returns a string representation of the Config object
606         * @method toString
607         * @return {String} The Config object in string format.
608         */
609         toString: function () {
610             var output = "Config";
611             if (this.owner) {
612                 output += " [" + this.owner.toString() + "]";
613             }
614             return output;
615         },
616         
617         /**
618         * Returns a string representation of the Config object's current 
619         * CustomEvent queue
620         * @method outputEventQueue
621         * @return {String} The string list of CustomEvents currently queued 
622         * for execution
623         */
624         outputEventQueue: function () {
626             var output = "",
627                 queueItem,
628                 q,
629                 nQueue = this.eventQueue.length;
630               
631             for (q = 0; q < nQueue; q++) {
632                 queueItem = this.eventQueue[q];
633                 if (queueItem) {
634                     output += queueItem[0] + "=" + queueItem[1] + ", ";
635                 }
636             }
637             return output;
638         },
640         /**
641         * Sets all properties to null, unsubscribes all listeners from each 
642         * property's change event and all listeners from the configChangedEvent.
643         * @method destroy
644         */
645         destroy: function () {
647             var oConfig = this.config,
648                 sProperty,
649                 oProperty;
652             for (sProperty in oConfig) {
653             
654                 if (Lang.hasOwnProperty(oConfig, sProperty)) {
656                     oProperty = oConfig[sProperty];
658                     oProperty.event.unsubscribeAll();
659                     oProperty.event = null;
661                 }
662             
663             }
664             
665             this.configChangedEvent.unsubscribeAll();
666             
667             this.configChangedEvent = null;
668             this.owner = null;
669             this.config = null;
670             this.initialConfig = null;
671             this.eventQueue = null;
672         
673         }
675     };
676     
677     
678     
679     /**
680     * Checks to determine if a particular function/Object pair are already 
681     * subscribed to the specified CustomEvent
682     * @method YAHOO.util.Config.alreadySubscribed
683     * @static
684     * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check 
685     * the subscriptions
686     * @param {Function} fn The function to look for in the subscribers list
687     * @param {Object} obj The execution scope Object for the subscription
688     * @return {Boolean} true, if the function/Object pair is already subscribed 
689     * to the CustomEvent passed in
690     */
691     Config.alreadySubscribed = function (evt, fn, obj) {
692     
693         var nSubscribers = evt.subscribers.length,
694             subsc,
695             i;
697         if (nSubscribers > 0) {
699             i = nSubscribers - 1;
700         
701             do {
703                 subsc = evt.subscribers[i];
705                 if (subsc && subsc.obj == obj && subsc.fn == fn) {
706         
707                     return true;
708         
709                 }    
710             
711             }
712             while (i--);
713         
714         }
715     
716         return false;
717     
718     };
719     
720     YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
722 }());
723 (function () {
725     /**
726     * The Container family of components is designed to enable developers to 
727     * create different kinds of content-containing modules on the web. Module 
728     * and Overlay are the most basic containers, and they can be used directly 
729     * or extended to build custom containers. Also part of the Container family 
730     * are four UI controls that extend Module and Overlay: Tooltip, Panel, 
731     * Dialog, and SimpleDialog.
732     * @module container
733     * @title Container
734     * @requires yahoo, dom, event 
735     * @optional dragdrop, animation, button
736     */
737     
738     /**
739     * Module is a JavaScript representation of the Standard Module Format. 
740     * Standard Module Format is a simple standard for markup containers where 
741     * child nodes representing the header, body, and footer of the content are 
742     * denoted using the CSS classes "hd", "bd", and "ft" respectively. 
743     * Module is the base class for all other classes in the YUI 
744     * Container package.
745     * @namespace YAHOO.widget
746     * @class Module
747     * @constructor
748     * @param {String} el The element ID representing the Module <em>OR</em>
749     * @param {HTMLElement} el The element representing the Module
750     * @param {Object} userConfig The configuration Object literal containing 
751     * the configuration that should be set for this module. See configuration 
752     * documentation for more details.
753     */
754     YAHOO.widget.Module = function (el, userConfig) {
755     
756         if (el) {
757     
758             this.init(el, userConfig);
759     
760         } else {
761     
762             YAHOO.log("No element or element ID specified" + 
763                 " for Module instantiation", "error");
764     
765         }
766     
767     };
770     var Dom = YAHOO.util.Dom,
771         Config = YAHOO.util.Config,
772         Event = YAHOO.util.Event,
773         CustomEvent = YAHOO.util.CustomEvent,
774         Module = YAHOO.widget.Module,
775         
776         m_oModuleTemplate,
777         m_oHeaderTemplate,
778         m_oBodyTemplate,
779         m_oFooterTemplate,
781         /**
782         * Constant representing the name of the Module's events
783         * @property EVENT_TYPES
784         * @private
785         * @final
786         * @type Object
787         */
788         EVENT_TYPES = {
789         
790             "BEFORE_INIT": "beforeInit",
791             "INIT": "init",
792             "APPEND": "append",
793             "BEFORE_RENDER": "beforeRender",
794             "RENDER": "render",
795             "CHANGE_HEADER": "changeHeader",
796             "CHANGE_BODY": "changeBody",
797             "CHANGE_FOOTER": "changeFooter",
798             "CHANGE_CONTENT": "changeContent",
799             "DESTORY": "destroy",
800             "BEFORE_SHOW": "beforeShow",
801             "SHOW": "show",
802             "BEFORE_HIDE": "beforeHide",
803             "HIDE": "hide"
804         
805         },
806             
807         /**
808         * Constant representing the Module's configuration properties
809         * @property DEFAULT_CONFIG
810         * @private
811         * @final
812         * @type Object
813         */
814         DEFAULT_CONFIG = {
815         
816             "VISIBLE": { 
817                 key: "visible", 
818                 value: true, 
819                 validator: YAHOO.lang.isBoolean 
820             },
821         
822             "EFFECT": { 
823                 key: "effect", 
824                 suppressEvent: true, 
825                 supercedes: ["visible"] 
826             },
827         
828             "MONITOR_RESIZE": { 
829                 key: "monitorresize", 
830                 value: true  
831             }
832         
833         };
835     
836     /**
837     * Constant representing the prefix path to use for non-secure images
838     * @property YAHOO.widget.Module.IMG_ROOT
839     * @static
840     * @final
841     * @type String
842     */
843     Module.IMG_ROOT = null;
844     
845     /**
846     * Constant representing the prefix path to use for securely served images
847     * @property YAHOO.widget.Module.IMG_ROOT_SSL
848     * @static
849     * @final
850     * @type String
851     */
852     Module.IMG_ROOT_SSL = null;
853     
854     /**
855     * Constant for the default CSS class name that represents a Module
856     * @property YAHOO.widget.Module.CSS_MODULE
857     * @static
858     * @final
859     * @type String
860     */
861     Module.CSS_MODULE = "yui-module";
862     
863     /**
864     * Constant representing the module header
865     * @property YAHOO.widget.Module.CSS_HEADER
866     * @static
867     * @final
868     * @type String
869     */
870     Module.CSS_HEADER = "hd";
871     
872     /**
873     * Constant representing the module body
874     * @property YAHOO.widget.Module.CSS_BODY
875     * @static
876     * @final
877     * @type String
878     */
879     Module.CSS_BODY = "bd";
880     
881     /**
882     * Constant representing the module footer
883     * @property YAHOO.widget.Module.CSS_FOOTER
884     * @static
885     * @final
886     * @type String
887     */
888     Module.CSS_FOOTER = "ft";
889     
890     /**
891     * Constant representing the url for the "src" attribute of the iframe 
892     * used to monitor changes to the browser's base font size
893     * @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
894     * @static
895     * @final
896     * @type String
897     */
898     Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
899     
900     /**
901     * Singleton CustomEvent fired when the font size is changed in the browser.
902     * Opera's "zoom" functionality currently does not support text 
903     * size detection.
904     * @event YAHOO.widget.Module.textResizeEvent
905     */
906     Module.textResizeEvent = new CustomEvent("textResize");
909     function createModuleTemplate() {
911         if (!m_oModuleTemplate) {
913             m_oModuleTemplate = document.createElement("div");
914             
915             m_oModuleTemplate.innerHTML = ("<div class=\"" + 
916                 Module.CSS_HEADER + "\"></div>" + "<div class=\"" + 
917                 Module.CSS_BODY + "\"></div><div class=\"" + 
918                 Module.CSS_FOOTER + "\"></div>");
920             m_oHeaderTemplate = m_oModuleTemplate.firstChild;
921             m_oBodyTemplate = m_oHeaderTemplate.nextSibling;
922             m_oFooterTemplate = m_oBodyTemplate.nextSibling;
924         }
926         return m_oModuleTemplate;
928     }
931     function createHeader() {
933         if (!m_oHeaderTemplate) {
934         
935             createModuleTemplate();
936         
937         }
938         
939         return (m_oHeaderTemplate.cloneNode(false));
941     }
942     
944     function createBody() {
946         if (!m_oBodyTemplate) {
947         
948             createModuleTemplate();
949         
950         }
951         
952         return (m_oBodyTemplate.cloneNode(false));
953     
954     }
955     
957     function createFooter() {
959         if (!m_oFooterTemplate) {
960         
961             createModuleTemplate();
962         
963         }
964         
965         return (m_oFooterTemplate.cloneNode(false));
967     }
968     
970     Module.prototype = {
971     
972         /**
973         * The class's constructor function
974         * @property contructor
975         * @type Function
976         */
977         constructor: Module,
978         
979         /**
980         * The main module element that contains the header, body, and footer
981         * @property element
982         * @type HTMLElement
983         */
984         element: null,
985         
986         /**
987         * The header element, denoted with CSS class "hd"
988         * @property header
989         * @type HTMLElement
990         */
991         header: null,
992         
993         /**
994         * The body element, denoted with CSS class "bd"
995         * @property body
996         * @type HTMLElement
997         */
998         body: null,
999         
1000         /**
1001         * The footer element, denoted with CSS class "ft"
1002         * @property footer
1003         * @type HTMLElement
1004         */
1005         footer: null,
1006         
1007         /**
1008         * The id of the element
1009         * @property id
1010         * @type String
1011         */
1012         id: null,
1013         
1014         /**
1015         * A string representing the root path for all images created by
1016         * a Module instance.
1017         * @deprecated It is recommend that any images for a Module be applied
1018         * via CSS using the "background-image" property.
1019         * @property imageRoot
1020         * @type String
1021         */
1022         imageRoot: Module.IMG_ROOT,
1023     
1024         /**
1025         * Initializes the custom events for Module which are fired 
1026         * automatically at appropriate times by the Module class.
1027         * @method initEvents
1028         */
1029         initEvents: function () {
1030         
1031             var SIGNATURE = CustomEvent.LIST;
1032         
1033             /**
1034             * CustomEvent fired prior to class initalization.
1035             * @event beforeInitEvent
1036             * @param {class} classRef class reference of the initializing 
1037             * class, such as this.beforeInitEvent.fire(Module)
1038             */
1039             this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT);
1040             this.beforeInitEvent.signature = SIGNATURE;
1041         
1042             /**
1043             * CustomEvent fired after class initalization.
1044             * @event initEvent
1045             * @param {class} classRef class reference of the initializing 
1046             * class, such as this.beforeInitEvent.fire(Module)
1047             */  
1048             this.initEvent = this.createEvent(EVENT_TYPES.INIT);
1049             this.initEvent.signature = SIGNATURE;
1050         
1051             /**
1052             * CustomEvent fired when the Module is appended to the DOM
1053             * @event appendEvent
1054             */
1055             this.appendEvent = this.createEvent(EVENT_TYPES.APPEND);
1056             this.appendEvent.signature = SIGNATURE;
1057         
1058             /**
1059             * CustomEvent fired before the Module is rendered
1060             * @event beforeRenderEvent
1061             */
1062             this.beforeRenderEvent = 
1063                 this.createEvent(EVENT_TYPES.BEFORE_RENDER);
1064             this.beforeRenderEvent.signature = SIGNATURE;
1065         
1066             /**
1067             * CustomEvent fired after the Module is rendered
1068             * @event renderEvent
1069             */
1070             this.renderEvent = this.createEvent(EVENT_TYPES.RENDER);
1071             this.renderEvent.signature = SIGNATURE;
1072         
1073             /**
1074             * CustomEvent fired when the header content of the Module 
1075             * is modified
1076             * @event changeHeaderEvent
1077             * @param {String/HTMLElement} content String/element representing 
1078             * the new header content
1079             */
1080             this.changeHeaderEvent = 
1081                 this.createEvent(EVENT_TYPES.CHANGE_HEADER);
1082             this.changeHeaderEvent.signature = SIGNATURE;
1083             
1084             /**
1085             * CustomEvent fired when the body content of the Module is modified
1086             * @event changeBodyEvent
1087             * @param {String/HTMLElement} content String/element representing 
1088             * the new body content
1089             */  
1090             this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY);
1091             this.changeBodyEvent.signature = SIGNATURE;
1092             
1093             /**
1094             * CustomEvent fired when the footer content of the Module 
1095             * is modified
1096             * @event changeFooterEvent
1097             * @param {String/HTMLElement} content String/element representing 
1098             * the new footer content
1099             */
1100             this.changeFooterEvent = 
1101                 this.createEvent(EVENT_TYPES.CHANGE_FOOTER);
1102             this.changeFooterEvent.signature = SIGNATURE;
1103         
1104             /**
1105             * CustomEvent fired when the content of the Module is modified
1106             * @event changeContentEvent
1107             */
1108             this.changeContentEvent = 
1109                 this.createEvent(EVENT_TYPES.CHANGE_CONTENT);
1110             this.changeContentEvent.signature = SIGNATURE;
1111         
1112             /**
1113             * CustomEvent fired when the Module is destroyed
1114             * @event destroyEvent
1115             */
1116             this.destroyEvent = this.createEvent(EVENT_TYPES.DESTORY);
1117             this.destroyEvent.signature = SIGNATURE;
1118             
1119             /**
1120             * CustomEvent fired before the Module is shown
1121             * @event beforeShowEvent
1122             */
1123             this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW);
1124             this.beforeShowEvent.signature = SIGNATURE;
1125         
1126             /**
1127             * CustomEvent fired after the Module is shown
1128             * @event showEvent
1129             */
1130             this.showEvent = this.createEvent(EVENT_TYPES.SHOW);
1131             this.showEvent.signature = SIGNATURE;
1132         
1133             /**
1134             * CustomEvent fired before the Module is hidden
1135             * @event beforeHideEvent
1136             */
1137             this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE);
1138             this.beforeHideEvent.signature = SIGNATURE;
1139         
1140             /**
1141             * CustomEvent fired after the Module is hidden
1142             * @event hideEvent
1143             */
1144             this.hideEvent = this.createEvent(EVENT_TYPES.HIDE);
1145             this.hideEvent.signature = SIGNATURE;
1146         }, 
1147         
1148         /**
1149         * String representing the current user-agent platform
1150         * @property platform
1151         * @type String
1152         */
1153         platform: function () {
1154         
1155             var ua = navigator.userAgent.toLowerCase();
1156         
1157             if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
1158         
1159                 return "windows";
1160         
1161             } else if (ua.indexOf("macintosh") != -1) {
1162         
1163                 return "mac";
1164         
1165             } else {
1166         
1167                 return false;
1168         
1169             }
1170         
1171         }(),
1172         
1173         /**
1174         * String representing the user-agent of the browser
1175         * @deprecated Use YAHOO.env.ua
1176         * @property browser
1177         * @type String
1178         */
1179         browser: function () {
1180         
1181             var ua = navigator.userAgent.toLowerCase();
1182             
1183             /*
1184                  Check Opera first in case of spoof and check Safari before
1185                  Gecko since Safari's user agent string includes "like Gecko"
1186             */
1188             if (ua.indexOf('opera') != -1) { 
1189             
1190                 return 'opera';
1191             
1192             } else if (ua.indexOf('msie 7') != -1) {
1193             
1194                 return 'ie7';
1195             
1196             } else if (ua.indexOf('msie') != -1) {
1197             
1198                 return 'ie';
1199             
1200             } else if (ua.indexOf('safari') != -1) { 
1201             
1202                 return 'safari';
1203             
1204             } else if (ua.indexOf('gecko') != -1) {
1205             
1206                 return 'gecko';
1207             
1208             } else {
1209             
1210                 return false;
1211             
1212             }
1213         
1214         }(),
1215         
1216         /**
1217         * Boolean representing whether or not the current browsing context is 
1218         * secure (https)
1219         * @property isSecure
1220         * @type Boolean
1221         */
1222         isSecure: function () {
1223         
1224             if (window.location.href.toLowerCase().indexOf("https") === 0) {
1225         
1226                 return true;
1227         
1228             } else {
1229         
1230                 return false;
1231         
1232             }
1233         
1234         }(),
1235         
1236         /**
1237         * Initializes the custom events for Module which are fired 
1238         * automatically at appropriate times by the Module class.
1239         */
1240         initDefaultConfig: function () {
1241     
1242             // Add properties //
1243         
1244             /**
1245             * Specifies whether the Module is visible on the page.
1246             * @config visible
1247             * @type Boolean
1248             * @default true
1249             */
1250             this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, {
1251                 handler: this.configVisible, 
1252                 value: DEFAULT_CONFIG.VISIBLE.value, 
1253                 validator: DEFAULT_CONFIG.VISIBLE.validator
1254             });
1255             
1256             /**
1257             * Object or array of objects representing the ContainerEffect 
1258             * classes that are active for animating the container.
1259             * @config effect
1260             * @type Object
1261             * @default null
1262             */
1263             this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, {
1264                 suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent, 
1265                 supercedes: DEFAULT_CONFIG.EFFECT.supercedes
1266             });
1267             
1268             /**
1269             * Specifies whether to create a special proxy iframe to monitor 
1270             * for user font resizing in the document
1271             * @config monitorresize
1272             * @type Boolean
1273             * @default true
1274             */
1275             this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, {
1276                 handler: this.configMonitorResize,
1277                 value: DEFAULT_CONFIG.MONITOR_RESIZE.value
1278             });
1279             
1280         },
1281         
1282         /**
1283         * The Module class's initialization method, which is executed for
1284         * Module and all of its subclasses. This method is automatically 
1285         * called by the constructor, and  sets up all DOM references for 
1286         * pre-existing markup, and creates required markup if it is not 
1287         * already present.
1288         * @method init
1289         * @param {String} el The element ID representing the Module <em>OR</em>
1290         * @param {HTMLElement} el The element representing the Module
1291         * @param {Object} userConfig The configuration Object literal 
1292         * containing the configuration that should be set for this module. 
1293         * See configuration documentation for more details.
1294         */
1295         init: function (el, userConfig) {
1296         
1297             var elId, i, child;
1298         
1299             this.initEvents();
1300         
1301             this.beforeInitEvent.fire(Module);
1302         
1303             /**
1304             * The Module's Config object used for monitoring 
1305             * configuration properties.
1306             * @property cfg
1307             * @type YAHOO.util.Config
1308             */
1309             this.cfg = new Config(this);
1310         
1311             if (this.isSecure) {
1312                 this.imageRoot = Module.IMG_ROOT_SSL;
1313             }
1314         
1315             if (typeof el == "string") {
1317                 elId = el;
1318         
1319                 el = document.getElementById(el);
1321                 if (! el) {
1323                     el = (createModuleTemplate()).cloneNode(false);
1325                     el.id = elId;
1327                 }
1329             }
1330         
1331             this.element = el;
1332         
1333             if (el.id) {
1334                 this.id = el.id;
1335             }
1336         
1337             child = this.element.firstChild;
1338             
1339             if (child) {
1341                 do {
1343                     switch (child.className) {
1344     
1345                     case Module.CSS_HEADER:
1346     
1347                         this.header = child;
1348     
1349                         break;
1350     
1351                     case Module.CSS_BODY:
1352     
1353                         this.body = child;
1354     
1355                         break;
1356     
1357                     case Module.CSS_FOOTER:
1358     
1359                         this.footer = child;
1360     
1361                         break;
1362     
1363                     }
1364                     
1365                 } while ((child = child.nextSibling));
1366             
1367             }
1369         
1370             this.initDefaultConfig();
1371         
1372             Dom.addClass(this.element, Module.CSS_MODULE);
1373         
1374             if (userConfig) {
1375                 this.cfg.applyConfig(userConfig, true);
1376             }
1377         
1378             /*
1379                 Subscribe to the fireQueue() method of Config so that any 
1380                 queued configuration changes are excecuted upon render of 
1381                 the Module
1382             */ 
1383             
1384             if (!Config.alreadySubscribed(this.renderEvent, 
1385                 this.cfg.fireQueue, this.cfg)) {
1387                 this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
1389             }
1390         
1391             this.initEvent.fire(Module);
1392         },
1393         
1394         /**
1395         * Initialized an empty IFRAME that is placed out of the visible area 
1396         * that can be used to detect text resize.
1397         * @method initResizeMonitor
1398         */
1399         initResizeMonitor: function () {
1400         
1401             var oDoc, 
1402                 oIFrame, 
1403                 sHTML;
1404         
1405             function fireTextResize() {
1406         
1407                 Module.textResizeEvent.fire();
1408         
1409             }
1410         
1411             if (!YAHOO.env.ua.opera) {
1412         
1413                 oIFrame = Dom.get("_yuiResizeMonitor");
1414         
1415                 if (!oIFrame) {
1416         
1417                     oIFrame = document.createElement("iframe");
1418         
1419                     if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && 
1420                         YAHOO.env.ua.ie) {
1421     
1422                         oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL;
1423     
1424                     }
1427                     /*
1428                         Need to set "src" attribute of the iframe to 
1429                         prevent the browser from reporting duplicate 
1430                         cookies. (See SourceForge bug #1721755)
1431                     */
1432         
1433                     if (YAHOO.env.ua.gecko) {
1435                         sHTML = "<html><head><script " +
1436                                 "type=\"text/javascript\">" + 
1437                                 "window.onresize=function(){window.parent." +
1438                                 "YAHOO.widget.Module.textResizeEvent." +
1439                                 "fire();};window.parent.YAHOO.widget.Module." +
1440                                 "textResizeEvent.fire();</script></head>" + 
1441                                 "<body></body></html>";
1443                         oIFrame.src = "data:text/html;charset=utf-8," + 
1444                             encodeURIComponent(sHTML);
1446                     }
1448                     oIFrame.id = "_yuiResizeMonitor";
1449                     
1450                     /*
1451                         Need to set "position" property before inserting the 
1452                         iframe into the document or Safari's status bar will 
1453                         forever indicate the iframe is loading 
1454                         (See SourceForge bug #1723064)
1455                     */
1456                     
1457                     oIFrame.style.position = "absolute";
1458                     oIFrame.style.visibility = "hidden";
1459         
1460                     document.body.appendChild(oIFrame);
1461         
1462                     oIFrame.style.width = "10em";
1463                     oIFrame.style.height = "10em";
1464                     oIFrame.style.top = (-1 * oIFrame.offsetHeight) + "px";
1465                     oIFrame.style.left = (-1 * oIFrame.offsetWidth) + "px";
1466                     oIFrame.style.borderWidth = "0";
1467                     oIFrame.style.visibility = "visible";
1468         
1469                     if (YAHOO.env.ua.webkit) {
1470         
1471                         oDoc = oIFrame.contentWindow.document;
1472         
1473                         oDoc.open();
1474                         oDoc.close();
1475         
1476                     }
1478                 }
1479         
1480                 if (oIFrame && oIFrame.contentWindow) {
1482                     Module.textResizeEvent.subscribe(this.onDomResize, 
1483                         this, true);
1484         
1485                     if (!Module.textResizeInitialized) {
1487                         if (!Event.on(oIFrame.contentWindow, "resize", 
1488                             fireTextResize)) {
1490                             /*
1491                                  This will fail in IE if document.domain has 
1492                                  changed, so we must change the listener to 
1493                                  use the oIFrame element instead
1494                             */
1496                             Event.on(oIFrame, "resize", fireTextResize);
1498                         }
1500                         Module.textResizeInitialized = true;
1502                     }
1504                     this.resizeMonitor = oIFrame;
1506                 }
1507         
1508             }
1509         
1510         },
1511         
1512         /**
1513         * Event handler fired when the resize monitor element is resized.
1514         * @method onDomResize
1515         * @param {DOMEvent} e The DOM resize event
1516         * @param {Object} obj The scope object passed to the handler
1517         */
1518         onDomResize: function (e, obj) {
1519         
1520             var nLeft = -1 * this.resizeMonitor.offsetWidth,
1521                 nTop = -1 * this.resizeMonitor.offsetHeight;
1522         
1523             this.resizeMonitor.style.top = nTop + "px";
1524             this.resizeMonitor.style.left =  nLeft + "px";
1525         
1526         },
1527         
1528         /**
1529         * Sets the Module's header content to the HTML specified, or appends 
1530         * the passed element to the header. If no header is present, one will 
1531         * be automatically created.
1532         * @method setHeader
1533         * @param {String} headerContent The HTML used to set the header 
1534         * <em>OR</em>
1535         * @param {HTMLElement} headerContent The HTMLElement to append to 
1536         * the header
1537         */
1538         setHeader: function (headerContent) {
1540             var oHeader = this.header || (this.header = createHeader());
1541         
1542             if (typeof headerContent == "string") {
1544                 oHeader.innerHTML = headerContent;
1546             } else {
1548                 oHeader.innerHTML = "";
1549                 oHeader.appendChild(headerContent);
1551             }
1552         
1553             this.changeHeaderEvent.fire(headerContent);
1554             this.changeContentEvent.fire();
1556         },
1557         
1558         /**
1559         * Appends the passed element to the header. If no header is present, 
1560         * one will be automatically created.
1561         * @method appendToHeader
1562         * @param {HTMLElement} element The element to append to the header
1563         */
1564         appendToHeader: function (element) {
1566             var oHeader = this.header || (this.header = createHeader());
1567         
1568             oHeader.appendChild(element);
1570             this.changeHeaderEvent.fire(element);
1571             this.changeContentEvent.fire();
1573         },
1574         
1575         /**
1576         * Sets the Module's body content to the HTML specified, or appends the
1577         * passed element to the body. If no body is present, one will be 
1578         * automatically created.
1579         * @method setBody
1580         * @param {String} bodyContent The HTML used to set the body <em>OR</em>
1581         * @param {HTMLElement} bodyContent The HTMLElement to append to the body
1582         */
1583         setBody: function (bodyContent) {
1585             var oBody = this.body || (this.body = createBody());
1586         
1587             if (typeof bodyContent == "string") {
1589                 oBody.innerHTML = bodyContent;
1591             } else {
1593                 oBody.innerHTML = "";
1594                 oBody.appendChild(bodyContent);
1596             }
1597         
1598             this.changeBodyEvent.fire(bodyContent);
1599             this.changeContentEvent.fire();
1601         },
1602         
1603         /**
1604         * Appends the passed element to the body. If no body is present, one 
1605         * will be automatically created.
1606         * @method appendToBody
1607         * @param {HTMLElement} element The element to append to the body
1608         */
1609         appendToBody: function (element) {
1611             var oBody = this.body || (this.body = createBody());
1612         
1613             oBody.appendChild(element);
1615             this.changeBodyEvent.fire(element);
1616             this.changeContentEvent.fire();
1618         },
1619         
1620         /**
1621         * Sets the Module's footer content to the HTML specified, or appends 
1622         * the passed element to the footer. If no footer is present, one will 
1623         * be automatically created.
1624         * @method setFooter
1625         * @param {String} footerContent The HTML used to set the footer 
1626         * <em>OR</em>
1627         * @param {HTMLElement} footerContent The HTMLElement to append to 
1628         * the footer
1629         */
1630         setFooter: function (footerContent) {
1632             var oFooter = this.footer || (this.footer = createFooter());
1633         
1634             if (typeof footerContent == "string") {
1636                 oFooter.innerHTML = footerContent;
1638             } else {
1640                 oFooter.innerHTML = "";
1641                 oFooter.appendChild(footerContent);
1643             }
1644         
1645             this.changeFooterEvent.fire(footerContent);
1646             this.changeContentEvent.fire();
1648         },
1649         
1650         /**
1651         * Appends the passed element to the footer. If no footer is present, 
1652         * one will be automatically created.
1653         * @method appendToFooter
1654         * @param {HTMLElement} element The element to append to the footer
1655         */
1656         appendToFooter: function (element) {
1658             var oFooter = this.footer || (this.footer = createFooter());
1659         
1660             oFooter.appendChild(element);
1662             this.changeFooterEvent.fire(element);
1663             this.changeContentEvent.fire();
1665         },
1666         
1667         /**
1668         * Renders the Module by inserting the elements that are not already 
1669         * in the main Module into their correct places. Optionally appends 
1670         * the Module to the specified node prior to the render's execution. 
1671         * NOTE: For Modules without existing markup, the appendToNode argument 
1672         * is REQUIRED. If this argument is ommitted and the current element is 
1673         * not present in the document, the function will return false, 
1674         * indicating that the render was a failure.
1675         * @method render
1676         * @param {String} appendToNode The element id to which the Module 
1677         * should be appended to prior to rendering <em>OR</em>
1678         * @param {HTMLElement} appendToNode The element to which the Module 
1679         * should be appended to prior to rendering
1680         * @param {HTMLElement} moduleElement OPTIONAL. The element that 
1681         * represents the actual Standard Module container.
1682         * @return {Boolean} Success or failure of the render
1683         */
1684         render: function (appendToNode, moduleElement) {
1685         
1686             var me = this,
1687                 firstChild;
1688         
1689             function appendTo(element) {
1690                 if (typeof element == "string") {
1691                     element = document.getElementById(element);
1692                 }
1693         
1694                 if (element) {
1695                     element.appendChild(me.element);
1696                     me.appendEvent.fire();
1697                 }
1698             }
1699         
1700             this.beforeRenderEvent.fire();
1701         
1702             if (! moduleElement) {
1703                 moduleElement = this.element;
1704             }
1705         
1706             if (appendToNode) {
1708                 appendTo(appendToNode);
1710             } else { 
1712                 /*
1713                      No node was passed in. If the element is not already in 
1714                      the Dom, this fails
1715                 */
1717                 if (! Dom.inDocument(this.element)) {
1719                     YAHOO.log("Render failed. Must specify appendTo node if " + 
1720                         " Module isn't already in the DOM.", "error");
1722                     return false;
1724                 }
1726             }
1727         
1728             // Need to get everything into the DOM if it isn't already
1729         
1730             if (this.header && ! Dom.inDocument(this.header)) {
1732                 /*
1733                     There is a header, but it's not in the DOM yet... 
1734                     need to add it
1735                 */
1737                 firstChild = moduleElement.firstChild;
1739                 if (firstChild) { // Insert before first child if exists
1741                     moduleElement.insertBefore(this.header, firstChild);
1743                 } else { // Append to empty body because there are no children
1745                     moduleElement.appendChild(this.header);
1747                 }
1749             }
1750         
1751             if (this.body && ! Dom.inDocument(this.body)) {
1753                 /*
1754                      There is a body, but it's not in the DOM yet... 
1755                      need to add it
1756                 */
1759                 // Insert before footer if exists in DOM
1761                 if (this.footer && Dom.isAncestor(
1762                     this.moduleElement, this.footer)) { 
1764                     moduleElement.insertBefore(this.body, this.footer);
1766                 } else { // Append to element because there is no footer
1768                     moduleElement.appendChild(this.body);
1770                 }
1772             }
1773         
1774             if (this.footer && ! Dom.inDocument(this.footer)) {
1776                 /*
1777                      There is a footer, but it's not in the DOM yet... 
1778                      need to add it
1779                 */
1781                 moduleElement.appendChild(this.footer);
1783             }
1784         
1785             this.renderEvent.fire();
1786             return true;
1787         },
1788         
1789         /**
1790         * Removes the Module element from the DOM and sets all child elements 
1791         * to null.
1792         * @method destroy
1793         */
1794         destroy: function () {
1795         
1796             var parent,
1797                 e;
1798         
1799             if (this.element) {
1800                 Event.purgeElement(this.element, true);
1801                 parent = this.element.parentNode;
1802             }
1804             if (parent) {
1805                 parent.removeChild(this.element);
1806             }
1807         
1808             this.element = null;
1809             this.header = null;
1810             this.body = null;
1811             this.footer = null;
1813             Module.textResizeEvent.unsubscribe(this.onDomResize, this);
1815             this.cfg.destroy();
1816             this.cfg = null;
1818             this.destroyEvent.fire();
1819         
1820             for (e in this) {
1821                 if (e instanceof CustomEvent) {
1822                     e.unsubscribeAll();
1823                 }
1824             }
1826         },
1827         
1828         /**
1829         * Shows the Module element by setting the visible configuration 
1830         * property to true. Also fires two events: beforeShowEvent prior to 
1831         * the visibility change, and showEvent after.
1832         * @method show
1833         */
1834         show: function () {
1835             this.cfg.setProperty("visible", true);
1836         },
1837         
1838         /**
1839         * Hides the Module element by setting the visible configuration 
1840         * property to false. Also fires two events: beforeHideEvent prior to 
1841         * the visibility change, and hideEvent after.
1842         * @method hide
1843         */
1844         hide: function () {
1845             this.cfg.setProperty("visible", false);
1846         },
1847         
1848         // BUILT-IN EVENT HANDLERS FOR MODULE //
1849         
1850         /**
1851         * Default event handler for changing the visibility property of a 
1852         * Module. By default, this is achieved by switching the "display" style 
1853         * between "block" and "none".
1854         * This method is responsible for firing showEvent and hideEvent.
1855         * @param {String} type The CustomEvent type (usually the property name)
1856         * @param {Object[]} args The CustomEvent arguments. For configuration 
1857         * handlers, args[0] will equal the newly applied value for the property.
1858         * @param {Object} obj The scope object. For configuration handlers, 
1859         * this will usually equal the owner.
1860         * @method configVisible
1861         */
1862         configVisible: function (type, args, obj) {
1863             var visible = args[0];
1864             if (visible) {
1865                 this.beforeShowEvent.fire();
1866                 Dom.setStyle(this.element, "display", "block");
1867                 this.showEvent.fire();
1868             } else {
1869                 this.beforeHideEvent.fire();
1870                 Dom.setStyle(this.element, "display", "none");
1871                 this.hideEvent.fire();
1872             }
1873         },
1874         
1875         /**
1876         * Default event handler for the "monitorresize" configuration property
1877         * @param {String} type The CustomEvent type (usually the property name)
1878         * @param {Object[]} args The CustomEvent arguments. For configuration 
1879         * handlers, args[0] will equal the newly applied value for the property.
1880         * @param {Object} obj The scope object. For configuration handlers, 
1881         * this will usually equal the owner.
1882         * @method configMonitorResize
1883         */
1884         configMonitorResize: function (type, args, obj) {
1886             var monitor = args[0];
1888             if (monitor) {
1890                 this.initResizeMonitor();
1892             } else {
1894                 Module.textResizeEvent.unsubscribe(
1895                     this.onDomResize, this, true);
1897                 this.resizeMonitor = null;
1898             }
1900         },
1901         
1902         /**
1903         * Returns a String representation of the Object.
1904         * @method toString
1905         * @return {String} The string representation of the Module
1906         */
1907         toString: function () {
1908             return "Module " + this.id;
1909         }
1910         
1911     };
1912     
1913     YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
1915 }());
1916 (function () {
1918     /**
1919     * Overlay is a Module that is absolutely positioned above the page flow. It 
1920     * has convenience methods for positioning and sizing, as well as options for 
1921     * controlling zIndex and constraining the Overlay's position to the current 
1922     * visible viewport. Overlay also contains a dynamicly generated IFRAME which 
1923     * is placed beneath it for Internet Explorer 6 and 5.x so that it will be 
1924     * properly rendered above SELECT elements.
1925     * @namespace YAHOO.widget
1926     * @class Overlay
1927     * @extends Module
1928     * @param {String} el The element ID representing the Overlay <em>OR</em>
1929     * @param {HTMLElement} el The element representing the Overlay
1930     * @param {Object} userConfig The configuration object literal containing 
1931     * the configuration that should be set for this Overlay. See configuration 
1932     * documentation for more details.
1933     * @constructor
1934     */
1935     YAHOO.widget.Overlay = function (el, userConfig) {
1936     
1937         YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
1938     
1939     };
1942     var Lang = YAHOO.lang,
1943         CustomEvent = YAHOO.util.CustomEvent,
1944         Module = YAHOO.widget.Module,
1945         Event = YAHOO.util.Event,
1946         Dom = YAHOO.util.Dom,
1947         Config = YAHOO.util.Config,
1948         Overlay = YAHOO.widget.Overlay,
1949         
1950         m_oIFrameTemplate,
1952         /**
1953         * Constant representing the name of the Overlay's events
1954         * @property EVENT_TYPES
1955         * @private
1956         * @final
1957         * @type Object
1958         */
1959         EVENT_TYPES = {
1960         
1961             "BEFORE_MOVE": "beforeMove",
1962             "MOVE": "move"
1963         
1964         },
1965         
1966         /**
1967         * Constant representing the Overlay's configuration properties
1968         * @property DEFAULT_CONFIG
1969         * @private
1970         * @final
1971         * @type Object
1972         */
1973         DEFAULT_CONFIG = {
1974         
1975             "X": { 
1976                 key: "x", 
1977                 validator: Lang.isNumber, 
1978                 suppressEvent: true, 
1979                 supercedes: ["iframe"] 
1980             },
1981         
1982             "Y": { 
1983                 key: "y", 
1984                 validator: Lang.isNumber, 
1985                 suppressEvent: true, 
1986                 supercedes: ["iframe"] 
1987             },
1988         
1989             "XY": { 
1990                 key: "xy", 
1991                 suppressEvent: true, 
1992                 supercedes: ["iframe"] 
1993             },
1994         
1995             "CONTEXT": { 
1996                 key: "context", 
1997                 suppressEvent: true, 
1998                 supercedes: ["iframe"] 
1999             },
2000         
2001             "FIXED_CENTER": { 
2002                 key: "fixedcenter", 
2003                 value: false, 
2004                 validator: Lang.isBoolean, 
2005                 supercedes: ["iframe", "visible"] 
2006             },
2007         
2008             "WIDTH": { 
2009                 key: "width", 
2010                 suppressEvent: true, 
2011                 supercedes: ["context", "fixedcenter", "iframe"] 
2012             }, 
2013         
2014             "HEIGHT": { 
2015                 key: "height", 
2016                 suppressEvent: true, 
2017                 supercedes: ["context", "fixedcenter", "iframe"] 
2018             }, 
2019         
2020             "ZINDEX": { 
2021                 key: "zindex", 
2022                 value: null 
2023             }, 
2024         
2025             "CONSTRAIN_TO_VIEWPORT": { 
2026                 key: "constraintoviewport", 
2027                 value: false, 
2028                 validator: Lang.isBoolean, 
2029                 supercedes: ["iframe", "x", "y", "xy"] 
2030             }, 
2031         
2032             "IFRAME": { 
2033                 key: "iframe", 
2034                 value: (YAHOO.env.ua.ie == 6 ? true : false), 
2035                 validator: Lang.isBoolean, 
2036                 supercedes: ["zindex"] 
2037             }
2038         
2039         };
2042     /**
2043     * The URL that will be placed in the iframe
2044     * @property YAHOO.widget.Overlay.IFRAME_SRC
2045     * @static
2046     * @final
2047     * @type String
2048     */
2049     Overlay.IFRAME_SRC = "javascript:false;";
2051     /**
2052     * Number representing how much the iframe shim should be offset from each 
2053     * side of an Overlay instance.
2054     * @property YAHOO.widget.Overlay.IFRAME_SRC
2055     * @default 3
2056     * @static
2057     * @final
2058     * @type Number
2059     */
2060     Overlay.IFRAME_OFFSET = 3;
2061     
2062     /**
2063     * Constant representing the top left corner of an element, used for 
2064     * configuring the context element alignment
2065     * @property YAHOO.widget.Overlay.TOP_LEFT
2066     * @static
2067     * @final
2068     * @type String
2069     */
2070     Overlay.TOP_LEFT = "tl";
2071     
2072     /**
2073     * Constant representing the top right corner of an element, used for 
2074     * configuring the context element alignment
2075     * @property YAHOO.widget.Overlay.TOP_RIGHT
2076     * @static
2077     * @final
2078     * @type String
2079     */
2080     Overlay.TOP_RIGHT = "tr";
2081     
2082     /**
2083     * Constant representing the top bottom left corner of an element, used for 
2084     * configuring the context element alignment
2085     * @property YAHOO.widget.Overlay.BOTTOM_LEFT
2086     * @static
2087     * @final
2088     * @type String
2089     */
2090     Overlay.BOTTOM_LEFT = "bl";
2091     
2092     /**
2093     * Constant representing the bottom right corner of an element, used for 
2094     * configuring the context element alignment
2095     * @property YAHOO.widget.Overlay.BOTTOM_RIGHT
2096     * @static
2097     * @final
2098     * @type String
2099     */
2100     Overlay.BOTTOM_RIGHT = "br";
2101     
2102     /**
2103     * Constant representing the default CSS class used for an Overlay
2104     * @property YAHOO.widget.Overlay.CSS_OVERLAY
2105     * @static
2106     * @final
2107     * @type String
2108     */
2109     Overlay.CSS_OVERLAY = "yui-overlay";
2110     
2111     
2112     /**
2113     * A singleton CustomEvent used for reacting to the DOM event for 
2114     * window scroll
2115     * @event YAHOO.widget.Overlay.windowScrollEvent
2116     */
2117     Overlay.windowScrollEvent = new CustomEvent("windowScroll");
2118     
2119     /**
2120     * A singleton CustomEvent used for reacting to the DOM event for
2121     * window resize
2122     * @event YAHOO.widget.Overlay.windowResizeEvent
2123     */
2124     Overlay.windowResizeEvent = new CustomEvent("windowResize");
2125     
2126     /**
2127     * The DOM event handler used to fire the CustomEvent for window scroll
2128     * @method YAHOO.widget.Overlay.windowScrollHandler
2129     * @static
2130     * @param {DOMEvent} e The DOM scroll event
2131     */
2132     Overlay.windowScrollHandler = function (e) {
2133     
2134         if (YAHOO.env.ua.ie) {
2135     
2136             if (! window.scrollEnd) {
2137     
2138                 window.scrollEnd = -1;
2139     
2140             }
2141     
2142             clearTimeout(window.scrollEnd);
2143     
2144             window.scrollEnd = setTimeout(function () { 
2145             
2146                 Overlay.windowScrollEvent.fire(); 
2147     
2148             }, 1);
2149     
2150         } else {
2151     
2152             Overlay.windowScrollEvent.fire();
2153     
2154         }
2155     
2156     };
2157     
2158     /**
2159     * The DOM event handler used to fire the CustomEvent for window resize
2160     * @method YAHOO.widget.Overlay.windowResizeHandler
2161     * @static
2162     * @param {DOMEvent} e The DOM resize event
2163     */
2164     Overlay.windowResizeHandler = function (e) {
2165     
2166         if (YAHOO.env.ua.ie) {
2167     
2168             if (! window.resizeEnd) {
2169                 window.resizeEnd = -1;
2170             }
2171     
2172             clearTimeout(window.resizeEnd);
2173     
2174             window.resizeEnd = setTimeout(function () {
2175     
2176                 Overlay.windowResizeEvent.fire(); 
2177     
2178             }, 100);
2179     
2180         } else {
2181     
2182             Overlay.windowResizeEvent.fire();
2183     
2184         }
2185     
2186     };
2187     
2188     /**
2189     * A boolean that indicated whether the window resize and scroll events have 
2190     * already been subscribed to.
2191     * @property YAHOO.widget.Overlay._initialized
2192     * @private
2193     * @type Boolean
2194     */
2195     Overlay._initialized = null;
2196     
2197     if (Overlay._initialized === null) {
2198     
2199         Event.on(window, "scroll", Overlay.windowScrollHandler);
2200         Event.on(window, "resize", Overlay.windowResizeHandler);
2201     
2202         Overlay._initialized = true;
2203     
2204     }
2205     
2206     YAHOO.extend(Overlay, Module, {
2207     
2208         /**
2209         * The Overlay initialization method, which is executed for Overlay and  
2210         * all of its subclasses. This method is automatically called by the 
2211         * constructor, and  sets up all DOM references for pre-existing markup, 
2212         * and creates required markup if it is not already present.
2213         * @method init
2214         * @param {String} el The element ID representing the Overlay <em>OR</em>
2215         * @param {HTMLElement} el The element representing the Overlay
2216         * @param {Object} userConfig The configuration object literal 
2217         * containing the configuration that should be set for this Overlay. 
2218         * See configuration documentation for more details.
2219         */
2220         init: function (el, userConfig) {
2221     
2222             /*
2223                  Note that we don't pass the user config in here yet because we
2224                  only want it executed once, at the lowest subclass level
2225             */
2226     
2227             Overlay.superclass.init.call(this, el/*, userConfig*/);  
2228             
2229             this.beforeInitEvent.fire(Overlay);
2230             
2231             Dom.addClass(this.element, Overlay.CSS_OVERLAY);
2232             
2233             if (userConfig) {
2234     
2235                 this.cfg.applyConfig(userConfig, true);
2236     
2237             }
2238             
2239             if (this.platform == "mac" && YAHOO.env.ua.gecko) {
2240     
2241                 if (! Config.alreadySubscribed(this.showEvent,
2242                     this.showMacGeckoScrollbars, this)) {
2243     
2244                     this.showEvent.subscribe(this.showMacGeckoScrollbars, 
2245                         this, true);
2246     
2247                 }
2248     
2249                 if (! Config.alreadySubscribed(this.hideEvent, 
2250                     this.hideMacGeckoScrollbars, this)) {
2251     
2252                     this.hideEvent.subscribe(this.hideMacGeckoScrollbars, 
2253                         this, true);
2254     
2255                 }
2256     
2257             }
2258             
2259             this.initEvent.fire(Overlay);
2260         
2261         },
2262         
2263         /**
2264         * Initializes the custom events for Overlay which are fired  
2265         * automatically at appropriate times by the Overlay class.
2266         * @method initEvents
2267         */
2268         initEvents: function () {
2269     
2270             Overlay.superclass.initEvents.call(this);
2271             
2272             var SIGNATURE = CustomEvent.LIST;
2273             
2274             /**
2275             * CustomEvent fired before the Overlay is moved.
2276             * @event beforeMoveEvent
2277             * @param {Number} x x coordinate
2278             * @param {Number} y y coordinate
2279             */
2280             this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
2281             this.beforeMoveEvent.signature = SIGNATURE;
2282             
2283             /**
2284             * CustomEvent fired after the Overlay is moved.
2285             * @event moveEvent
2286             * @param {Number} x x coordinate
2287             * @param {Number} y y coordinate
2288             */
2289             this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
2290             this.moveEvent.signature = SIGNATURE;
2291         
2292         },
2293         
2294         /**
2295         * Initializes the class's configurable properties which can be changed 
2296         * using the Overlay's Config object (cfg).
2297         * @method initDefaultConfig
2298         */
2299         initDefaultConfig: function () {
2300     
2301             Overlay.superclass.initDefaultConfig.call(this);
2302             
2303             
2304             // Add overlay config properties //
2305             
2306             /**
2307             * The absolute x-coordinate position of the Overlay
2308             * @config x
2309             * @type Number
2310             * @default null
2311             */
2312             this.cfg.addProperty(DEFAULT_CONFIG.X.key, { 
2313     
2314                 handler: this.configX, 
2315                 validator: DEFAULT_CONFIG.X.validator, 
2316                 suppressEvent: DEFAULT_CONFIG.X.suppressEvent, 
2317                 supercedes: DEFAULT_CONFIG.X.supercedes
2318     
2319             });
2320         
2321     
2322             /**
2323             * The absolute y-coordinate position of the Overlay
2324             * @config y
2325             * @type Number
2326             * @default null
2327             */
2328             this.cfg.addProperty(DEFAULT_CONFIG.Y.key, {
2329     
2330                 handler: this.configY, 
2331                 validator: DEFAULT_CONFIG.Y.validator, 
2332                 suppressEvent: DEFAULT_CONFIG.Y.suppressEvent, 
2333                 supercedes: DEFAULT_CONFIG.Y.supercedes
2334     
2335             });
2336         
2337     
2338             /**
2339             * An array with the absolute x and y positions of the Overlay
2340             * @config xy
2341             * @type Number[]
2342             * @default null
2343             */
2344             this.cfg.addProperty(DEFAULT_CONFIG.XY.key, {
2345             
2346                 handler: this.configXY, 
2347                 suppressEvent: DEFAULT_CONFIG.XY.suppressEvent, 
2348                 supercedes: DEFAULT_CONFIG.XY.supercedes
2349             
2350             });
2351         
2352     
2353             /**
2354             * The array of context arguments for context-sensitive positioning.  
2355             * The format is: [id or element, element corner, context corner]. 
2356             * For example, setting this property to ["img1", "tl", "bl"] would 
2357             * align the Overlay's top left corner to the context element's 
2358             * bottom left corner.
2359             * @config context
2360             * @type Array
2361             * @default null
2362             */
2363             this.cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
2364             
2365                 handler: this.configContext, 
2366                 suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent, 
2367                 supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
2368             
2369             });
2370         
2371     
2372             /**
2373             * True if the Overlay should be anchored to the center of 
2374             * the viewport.
2375             * @config fixedcenter
2376             * @type Boolean
2377             * @default false
2378             */
2379             this.cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
2380             
2381                 handler: this.configFixedCenter,
2382                 value: DEFAULT_CONFIG.FIXED_CENTER.value, 
2383                 validator: DEFAULT_CONFIG.FIXED_CENTER.validator, 
2384                 supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
2385             
2386             });
2387         
2388     
2389             /**
2390             * CSS width of the Overlay.
2391             * @config width
2392             * @type String
2393             * @default null
2394             */
2395             this.cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
2396             
2397                 handler: this.configWidth, 
2398                 suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent, 
2399                 supercedes: DEFAULT_CONFIG.WIDTH.supercedes
2400             
2401             });
2402             
2403             /**
2404             * CSS height of the Overlay.
2405             * @config height
2406             * @type String
2407             * @default null
2408             */
2409             this.cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
2410             
2411                 handler: this.configHeight, 
2412                 suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent, 
2413                 supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
2414             
2415             });
2416             
2417             /**
2418             * CSS z-index of the Overlay.
2419             * @config zIndex
2420             * @type Number
2421             * @default null
2422             */
2423             this.cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
2424     
2425                 handler: this.configzIndex,
2426                 value: DEFAULT_CONFIG.ZINDEX.value
2427     
2428             });
2429             
2430             /**
2431             * True if the Overlay should be prevented from being positioned 
2432             * out of the viewport.
2433             * @config constraintoviewport
2434             * @type Boolean
2435             * @default false
2436             */
2437             this.cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
2438             
2439                 handler: this.configConstrainToViewport, 
2440                 value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value, 
2441                 validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator, 
2442                 supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
2443             
2444             });
2445             
2446             /**
2447             * @config iframe
2448             * @description Boolean indicating whether or not the Overlay should 
2449             * have an IFRAME shim; used to prevent <SELECT> elements from 
2450             * poking through an Overlay instance in IE6.  When set to "true", 
2451             * the iframe shim is created when the Overlay instance is intially
2452             * made visible.
2453             * @type Boolean
2454             * @default true for IE6 and below, false for all other browsers.
2455             */
2456             this.cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
2457             
2458                 handler: this.configIframe, 
2459                 value: DEFAULT_CONFIG.IFRAME.value, 
2460                 validator: DEFAULT_CONFIG.IFRAME.validator, 
2461                 supercedes: DEFAULT_CONFIG.IFRAME.supercedes
2462             
2463             });
2464         
2465         },
2466         
2467         /**
2468         * Moves the Overlay to the specified position. This function is  
2469         * identical to calling this.cfg.setProperty("xy", [x,y]);
2470         * @method moveTo
2471         * @param {Number} x The Overlay's new x position
2472         * @param {Number} y The Overlay's new y position
2473         */
2474         moveTo: function (x, y) {
2475     
2476             this.cfg.setProperty("xy", [x, y]);
2477     
2478         },
2479         
2480         /**
2481         * Adds a CSS class ("hide-scrollbars") and removes a CSS class 
2482         * ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2483         * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2484         * @method hideMacGeckoScrollbars
2485         */
2486         hideMacGeckoScrollbars: function () {
2487     
2488             Dom.removeClass(this.element, "show-scrollbars");
2489             Dom.addClass(this.element, "hide-scrollbars");
2490     
2491         },
2492         
2493         /**
2494         * Adds a CSS class ("show-scrollbars") and removes a CSS class 
2495         * ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2496         * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2497         * @method showMacGeckoScrollbars
2498         */
2499         showMacGeckoScrollbars: function () {
2500     
2501             Dom.removeClass(this.element, "hide-scrollbars");
2502             Dom.addClass(this.element, "show-scrollbars");
2503     
2504         },
2505         
2506         // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
2507         
2508         /**
2509         * The default event handler fired when the "visible" property is 
2510         * changed.  This method is responsible for firing showEvent
2511         * and hideEvent.
2512         * @method configVisible
2513         * @param {String} type The CustomEvent type (usually the property name)
2514         * @param {Object[]} args The CustomEvent arguments. For configuration
2515         * handlers, args[0] will equal the newly applied value for the property.
2516         * @param {Object} obj The scope object. For configuration handlers, 
2517         * this will usually equal the owner.
2518         */
2519         configVisible: function (type, args, obj) {
2520     
2521             var visible = args[0],
2522                 currentVis = Dom.getStyle(this.element, "visibility"),
2523                 effect = this.cfg.getProperty("effect"),
2524                 effectInstances = [],
2525                 isMacGecko = (this.platform == "mac" && YAHOO.env.ua.gecko),
2526                 alreadySubscribed = Config.alreadySubscribed,
2527                 eff, ei, e, i, j, k, h,
2528                 nEffects,
2529                 nEffectInstances;
2530     
2531     
2532             if (currentVis == "inherit") {
2533     
2534                 e = this.element.parentNode;
2535     
2536                 while (e.nodeType != 9 && e.nodeType != 11) {
2537     
2538                     currentVis = Dom.getStyle(e, "visibility");
2539     
2540                     if (currentVis != "inherit") { 
2541     
2542                         break; 
2543     
2544                     }
2545     
2546                     e = e.parentNode;
2547     
2548                 }
2549     
2550                 if (currentVis == "inherit") {
2551     
2552                     currentVis = "visible";
2553                 
2554                 }
2555     
2556             }
2557         
2558     
2559             if (effect) {
2560     
2561                 if (effect instanceof Array) {
2563                     nEffects = effect.length;
2564     
2565                     for (i = 0; i < nEffects; i++) {
2566     
2567                         eff = effect[i];
2568     
2569                         effectInstances[effectInstances.length] = 
2570                             eff.effect(this, eff.duration);
2571     
2572                     }
2573     
2574                 } else {
2575     
2576                     effectInstances[effectInstances.length] = 
2577                         effect.effect(this, effect.duration);
2578     
2579                 }
2580     
2581             }
2582     
2583         
2584             if (visible) { // Show
2585     
2586                 if (isMacGecko) {
2587     
2588                     this.showMacGeckoScrollbars();
2589     
2590                 }
2591                 
2592     
2593                 if (effect) { // Animate in
2594     
2595     
2596                     if (visible) { // Animate in if not showing
2597     
2598     
2599                         if (currentVis != "visible" || currentVis === "") {
2600     
2601                             this.beforeShowEvent.fire();
2603                             nEffectInstances = effectInstances.length;
2604     
2605                             for (j = 0; j < nEffectInstances; j++) {
2606     
2607                                 ei = effectInstances[j];
2608     
2609                                 if (j === 0 && !alreadySubscribed(
2610                                         ei.animateInCompleteEvent, 
2611                                         this.showEvent.fire, this.showEvent)) {
2612     
2613                                     /*
2614                                          Delegate showEvent until end 
2615                                          of animateInComplete
2616                                     */
2617     
2618                                     ei.animateInCompleteEvent.subscribe(
2619                                      this.showEvent.fire, this.showEvent, true);
2620     
2621                                 }
2622     
2623                                 ei.animateIn();
2624     
2625                             }
2626     
2627                         }
2628     
2629                     }
2630     
2631                 } else { // Show
2632     
2633                     if (currentVis != "visible" || currentVis === "") {
2634     
2635                         this.beforeShowEvent.fire();
2636     
2637                         Dom.setStyle(this.element, "visibility", "visible");
2638     
2639                         this.cfg.refireEvent("iframe");
2640                         this.showEvent.fire();
2641     
2642                     }
2643         
2644                 }
2645         
2646             } else { // Hide
2647     
2648                 if (isMacGecko) {
2649     
2650                     this.hideMacGeckoScrollbars();
2651     
2652                 }
2653                     
2654                 if (effect) { // Animate out if showing
2655     
2656                     if (currentVis == "visible") {
2657     
2658                         this.beforeHideEvent.fire();
2660                         nEffectInstances = effectInstances.length;
2661     
2662                         for (k = 0; k < nEffectInstances; k++) {
2663     
2664                             h = effectInstances[k];
2665     
2666                             if (k === 0 && !alreadySubscribed(
2667                                 h.animateOutCompleteEvent, this.hideEvent.fire, 
2668                                 this.hideEvent)) {
2669     
2670                                 /*
2671                                      Delegate hideEvent until end 
2672                                      of animateOutComplete
2673                                 */
2674     
2675                                 h.animateOutCompleteEvent.subscribe(
2676                                     this.hideEvent.fire, this.hideEvent, true);
2677     
2678                             }
2679     
2680                             h.animateOut();
2681     
2682                         }
2683     
2684                     } else if (currentVis === "") {
2685     
2686                         Dom.setStyle(this.element, "visibility", "hidden");
2687     
2688                     }
2689     
2690                 } else { // Simple hide
2691     
2692                     if (currentVis == "visible" || currentVis === "") {
2693     
2694                         this.beforeHideEvent.fire();
2695     
2696                         Dom.setStyle(this.element, "visibility", "hidden");
2698                         this.hideEvent.fire();
2699     
2700                     }
2701     
2702                 }
2703     
2704             }
2705     
2706         },
2707         
2708         /**
2709         * Center event handler used for centering on scroll/resize, but only if 
2710         * the Overlay is visible
2711         * @method doCenterOnDOMEvent
2712         */
2713         doCenterOnDOMEvent: function () {
2714     
2715             if (this.cfg.getProperty("visible")) {
2716     
2717                 this.center();
2718     
2719             }
2720     
2721         },
2722         
2723         /**
2724         * The default event handler fired when the "fixedcenter" property 
2725         * is changed.
2726         * @method configFixedCenter
2727         * @param {String} type The CustomEvent type (usually the property name)
2728         * @param {Object[]} args The CustomEvent arguments. For configuration 
2729         * handlers, args[0] will equal the newly applied value for the property.
2730         * @param {Object} obj The scope object. For configuration handlers, 
2731         * this will usually equal the owner.
2732         */
2733         configFixedCenter: function (type, args, obj) {
2734     
2735             var val = args[0],
2736                 alreadySubscribed = Config.alreadySubscribed,
2737                 windowResizeEvent = Overlay.windowResizeEvent,
2738                 windowScrollEvent = Overlay.windowScrollEvent;
2739             
2740             if (val) {
2741     
2742                 this.center();
2743             
2744                 if (!alreadySubscribed(this.beforeShowEvent, 
2745                     this.center, this)) {
2746     
2747                     this.beforeShowEvent.subscribe(this.center);
2748     
2749                 }
2750             
2751                 if (!alreadySubscribed(windowResizeEvent, 
2752                     this.doCenterOnDOMEvent, this)) {
2753     
2754                     windowResizeEvent.subscribe(this.doCenterOnDOMEvent, 
2755                         this, true);
2756     
2757                 }
2758             
2759                 if (!alreadySubscribed(windowScrollEvent, 
2760                     this.doCenterOnDOMEvent, this)) {
2761         
2762                     windowScrollEvent.subscribe(this.doCenterOnDOMEvent, 
2763                         this, true);
2764     
2765                 }
2766     
2767             } else {
2768     
2769                 this.beforeShowEvent.unsubscribe(this.center);
2770     
2771                 windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2772                 windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2773     
2774             }
2775     
2776         },
2777         
2778         /**
2779         * The default event handler fired when the "height" property is changed.
2780         * @method configHeight
2781         * @param {String} type The CustomEvent type (usually the property name)
2782         * @param {Object[]} args The CustomEvent arguments. For configuration 
2783         * handlers, args[0] will equal the newly applied value for the property.
2784         * @param {Object} obj The scope object. For configuration handlers, 
2785         * this will usually equal the owner.
2786         */
2787         configHeight: function (type, args, obj) {
2788     
2789             var height = args[0],
2790                 el = this.element;
2791     
2792             Dom.setStyle(el, "height", height);
2793             this.cfg.refireEvent("iframe");
2794     
2795         },
2796         
2797         /**
2798         * The default event handler fired when the "width" property is changed.
2799         * @method configWidth
2800         * @param {String} type The CustomEvent type (usually the property name)
2801         * @param {Object[]} args The CustomEvent arguments. For configuration 
2802         * handlers, args[0] will equal the newly applied value for the property.
2803         * @param {Object} obj The scope object. For configuration handlers, 
2804         * this will usually equal the owner.
2805         */
2806         configWidth: function (type, args, obj) {
2807     
2808             var width = args[0],
2809                 el = this.element;
2810     
2811             Dom.setStyle(el, "width", width);
2812             this.cfg.refireEvent("iframe");
2813     
2814         },
2815         
2816         /**
2817         * The default event handler fired when the "zIndex" property is changed.
2818         * @method configzIndex
2819         * @param {String} type The CustomEvent type (usually the property name)
2820         * @param {Object[]} args The CustomEvent arguments. For configuration 
2821         * handlers, args[0] will equal the newly applied value for the property.
2822         * @param {Object} obj The scope object. For configuration handlers, 
2823         * this will usually equal the owner.
2824         */
2825         configzIndex: function (type, args, obj) {
2826     
2827             var zIndex = args[0],
2828                 el = this.element;
2829         
2830             if (! zIndex) {
2831     
2832                 zIndex = Dom.getStyle(el, "zIndex");
2833         
2834                 if (! zIndex || isNaN(zIndex)) {
2835     
2836                     zIndex = 0;
2837     
2838                 }
2839     
2840             }
2841             
2842             if (this.iframe) {
2843     
2844                 if (zIndex <= 0) {
2845     
2846                     zIndex = 1;
2847     
2848                 }
2849     
2850                 Dom.setStyle(this.iframe, "zIndex", (zIndex - 1));
2851             }
2852             
2853             Dom.setStyle(el, "zIndex", zIndex);
2854             this.cfg.setProperty("zIndex", zIndex, true);
2855     
2856         },
2857         
2858         /**
2859         * The default event handler fired when the "xy" property is changed.
2860         * @method configXY
2861         * @param {String} type The CustomEvent type (usually the property name)
2862         * @param {Object[]} args The CustomEvent arguments. For configuration 
2863         * handlers, args[0] will equal the newly applied value for the property.
2864         * @param {Object} obj The scope object. For configuration handlers, 
2865         * this will usually equal the owner.
2866         */
2867         configXY: function (type, args, obj) {
2868     
2869             var pos = args[0],
2870                 x = pos[0],
2871                 y = pos[1];
2872             
2873             this.cfg.setProperty("x", x);
2874             this.cfg.setProperty("y", y);
2875             
2876             this.beforeMoveEvent.fire([x, y]);
2877             
2878             x = this.cfg.getProperty("x");
2879             y = this.cfg.getProperty("y");
2880             
2881             YAHOO.log(("xy: " + [x, y]), "iframe");
2882             
2883             this.cfg.refireEvent("iframe");
2884             this.moveEvent.fire([x, y]);
2885     
2886         },
2887         
2888         /**
2889         * The default event handler fired when the "x" property is changed.
2890         * @method configX
2891         * @param {String} type The CustomEvent type (usually the property name)
2892         * @param {Object[]} args The CustomEvent arguments. For configuration 
2893         * handlers, args[0] will equal the newly applied value for the property.
2894         * @param {Object} obj The scope object. For configuration handlers, 
2895         * this will usually equal the owner.
2896         */
2897         configX: function (type, args, obj) {
2898     
2899             var x = args[0],
2900                 y = this.cfg.getProperty("y");
2901             
2902             this.cfg.setProperty("x", x, true);
2903             this.cfg.setProperty("y", y, true);
2904             
2905             this.beforeMoveEvent.fire([x, y]);
2906             
2907             x = this.cfg.getProperty("x");
2908             y = this.cfg.getProperty("y");
2909             
2910             Dom.setX(this.element, x, true);
2911             
2912             this.cfg.setProperty("xy", [x, y], true);
2913            
2914             this.cfg.refireEvent("iframe");
2915             this.moveEvent.fire([x, y]);
2916     
2917         },
2918         
2919         /**
2920         * The default event handler fired when the "y" property is changed.
2921         * @method configY
2922         * @param {String} type The CustomEvent type (usually the property name)
2923         * @param {Object[]} args The CustomEvent arguments. For configuration 
2924         * handlers, args[0] will equal the newly applied value for the property.
2925         * @param {Object} obj The scope object. For configuration handlers, 
2926         * this will usually equal the owner.
2927         */
2928         configY: function (type, args, obj) {
2929     
2930             var x = this.cfg.getProperty("x"),
2931                 y = args[0];
2932         
2933             this.cfg.setProperty("x", x, true);
2934             this.cfg.setProperty("y", y, true);
2935             
2936             this.beforeMoveEvent.fire([x, y]);
2937             
2938             x = this.cfg.getProperty("x");
2939             y = this.cfg.getProperty("y");
2940             
2941             Dom.setY(this.element, y, true);
2942             
2943             this.cfg.setProperty("xy", [x, y], true);
2944             
2945             this.cfg.refireEvent("iframe");
2946             this.moveEvent.fire([x, y]);
2947     
2948         },
2949         
2950         /**
2951         * Shows the iframe shim, if it has been enabled.
2952         * @method showIframe
2953         */
2954         showIframe: function () {
2956             var oIFrame = this.iframe,
2957                 oParentNode;
2959             if (oIFrame) {
2960     
2961                 oParentNode = this.element.parentNode;
2963                 if (oParentNode != oIFrame.parentNode) {
2965                     oParentNode.appendChild(oIFrame);
2966                 
2967                 }
2969                 oIFrame.style.display = "block";
2970     
2971             }
2972     
2973         },
2974         
2975         /**
2976         * Hides the iframe shim, if it has been enabled.
2977         * @method hideIframe
2978         */
2979         hideIframe: function () {
2980     
2981             if (this.iframe) {
2982     
2983                 this.iframe.style.display = "none";
2984     
2985             }
2986     
2987         },
2989         /**
2990         * Syncronizes the size and position of iframe shim to that of its 
2991         * corresponding Overlay instance.
2992         * @method syncIframe
2993         */
2994         syncIframe: function () {
2996             var oIFrame = this.iframe,
2997                 oElement = this.element,
2998                 nOffset = Overlay.IFRAME_OFFSET,
2999                 nDimensionOffset = (nOffset * 2),
3000                 aXY;
3003             if (oIFrame) {
3005                 // Size <iframe>
3007                 oIFrame.style.width = 
3008                     (oElement.offsetWidth + nDimensionOffset + "px");
3010                 oIFrame.style.height = 
3011                     (oElement.offsetHeight + nDimensionOffset + "px");
3014                 // Position <iframe>
3016                 aXY = this.cfg.getProperty("xy");
3018                 if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
3020                     this.syncPosition();
3022                     aXY = this.cfg.getProperty("xy");
3024                 }
3026                 Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
3028             }
3029         
3030         },
3032         
3033         /**
3034         * The default event handler fired when the "iframe" property is changed.
3035         * @method configIframe
3036         * @param {String} type The CustomEvent type (usually the property name)
3037         * @param {Object[]} args The CustomEvent arguments. For configuration 
3038         * handlers, args[0] will equal the newly applied value for the property.
3039         * @param {Object} obj The scope object. For configuration handlers, 
3040         * this will usually equal the owner.
3041         */
3042         configIframe: function (type, args, obj) {
3044             var bIFrame = args[0];
3046             function createIFrame() {
3048                 var oIFrame = this.iframe,
3049                     oElement = this.element,
3050                     oParent,
3051                     aXY;
3054                 if (!oIFrame) {
3056                     if (!m_oIFrameTemplate) {
3057     
3058                         m_oIFrameTemplate = document.createElement("iframe");
3060                         if (this.isSecure) {
3061         
3062                             m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
3063         
3064                         }
3066                         /*
3067                             Set the opacity of the <iframe> to 0 so that it 
3068                             doesn't modify the opacity of any transparent 
3069                             elements that may be on top of it (like a shadow).
3070                         */
3071         
3072                         if (YAHOO.env.ua.ie) {
3073         
3074                             m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
3075         
3076                             /*
3077                                  Need to set the "frameBorder" property to 0 
3078                                  supress the default <iframe> border in IE.  
3079                                  Setting the CSS "border" property alone 
3080                                  doesn't supress it.
3081                             */
3082         
3083                             m_oIFrameTemplate.frameBorder = 0;
3084         
3085                         }
3086                         else {
3087         
3088                             m_oIFrameTemplate.style.opacity = "0";
3089                         
3090                         }
3092                         m_oIFrameTemplate.style.position = "absolute";
3093                         m_oIFrameTemplate.style.border = "none";
3094                         m_oIFrameTemplate.style.margin = "0";
3095                         m_oIFrameTemplate.style.padding = "0";
3096                         m_oIFrameTemplate.style.display = "none";
3097     
3098                     }
3100                     oIFrame = m_oIFrameTemplate.cloneNode(false);
3102                     oParent = oElement.parentNode;
3104                     if (oParent) {
3106                         oParent.appendChild(oIFrame);
3108                     } else {
3110                         document.body.appendChild(oIFrame);
3112                     }
3113                     
3114                     this.iframe = oIFrame;
3116                 }
3119                 /*
3120                      Show the <iframe> before positioning it since the "setXY" 
3121                      method of DOM requires the element be in the document 
3122                      and visible.
3123                 */
3125                 this.showIframe();
3128                 /*
3129                      Syncronize the size and position of the <iframe> to that 
3130                      of the Overlay.
3131                 */
3132                 
3133                 this.syncIframe();
3136                 // Add event listeners to update the <iframe> when necessary
3138                 if (!this._hasIframeEventListeners) {
3140                     this.showEvent.subscribe(this.showIframe);
3141                     this.hideEvent.subscribe(this.hideIframe);
3142                     this.changeContentEvent.subscribe(this.syncIframe);
3144                     this._hasIframeEventListeners = true;
3145                     
3146                 }
3147                 
3148             }
3151             function onBeforeShow() {
3152             
3153                 createIFrame.call(this);
3154         
3155                 this.beforeShowEvent.unsubscribe(onBeforeShow);
3156                 
3157                 this._iframeDeferred = false;
3158             
3159             }
3160             
3162             if (bIFrame) { // <iframe> shim is enabled
3163                 
3164                 if (this.cfg.getProperty("visible")) {
3166                     createIFrame.call(this);
3167                 
3168                 }
3169                 else {
3171                     if (!this._iframeDeferred) {
3173                         this.beforeShowEvent.subscribe(onBeforeShow);
3175                         this._iframeDeferred = true;
3176                     
3177                     }
3178                 
3179                 }
3180     
3181             } else {    // <iframe> shim is disabled
3182     
3183                 this.hideIframe();
3185                 if (this._hasIframeEventListeners) {
3187                     this.showEvent.unsubscribe(this.showIframe);
3188                     this.hideEvent.unsubscribe(this.hideIframe);
3189                     this.changeContentEvent.unsubscribe(this.syncIframe);
3191                     this._hasIframeEventListeners = false;
3193                 }
3194                 
3195             }
3196     
3197         },
3198         
3199         
3200         /**
3201         * The default event handler fired when the "constraintoviewport" 
3202         * property is changed.
3203         * @method configConstrainToViewport
3204         * @param {String} type The CustomEvent type (usually the property name)
3205         * @param {Object[]} args The CustomEvent arguments. For configuration 
3206         * handlers, args[0] will equal the newly applied value for 
3207         * the property.
3208         * @param {Object} obj The scope object. For configuration handlers, 
3209         * this will usually equal the owner.
3210         */
3211         configConstrainToViewport: function (type, args, obj) {
3212     
3213             var val = args[0];
3214     
3215             if (val) {
3216     
3217                 if (! Config.alreadySubscribed(this.beforeMoveEvent, 
3218                     this.enforceConstraints, this)) {
3219     
3220                     this.beforeMoveEvent.subscribe(this.enforceConstraints, 
3221                         this, true);
3222     
3223                 }
3224     
3225             } else {
3226     
3227                 this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
3228     
3229             }
3230     
3231         },
3232         
3233         /**
3234         * The default event handler fired when the "context" property 
3235         * is changed.
3236         * @method configContext
3237         * @param {String} type The CustomEvent type (usually the property name)
3238         * @param {Object[]} args The CustomEvent arguments. For configuration 
3239         * handlers, args[0] will equal the newly applied value for the property.
3240         * @param {Object} obj The scope object. For configuration handlers, 
3241         * this will usually equal the owner.
3242         */
3243         configContext: function (type, args, obj) {
3244     
3245             var contextArgs = args[0],
3246                 contextEl,
3247                 elementMagnetCorner,
3248                 contextMagnetCorner;
3249             
3250             if (contextArgs) {
3251             
3252                 contextEl = contextArgs[0];
3253                 elementMagnetCorner = contextArgs[1];
3254                 contextMagnetCorner = contextArgs[2];
3255                 
3256                 if (contextEl) {
3257     
3258                     if (typeof contextEl == "string") {
3259     
3260                         this.cfg.setProperty("context", 
3261                             [document.getElementById(contextEl), 
3262                                 elementMagnetCorner, contextMagnetCorner], 
3263                                 true);
3264     
3265                     }
3266                     
3267                     if (elementMagnetCorner && contextMagnetCorner) {
3268     
3269                         this.align(elementMagnetCorner, contextMagnetCorner);
3270     
3271                     }
3272     
3273                 }
3274     
3275             }
3276     
3277         },
3278         
3279         
3280         // END BUILT-IN PROPERTY EVENT HANDLERS //
3281         
3282         /**
3283         * Aligns the Overlay to its context element using the specified corner 
3284         * points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, 
3285         * and BOTTOM_RIGHT.
3286         * @method align
3287         * @param {String} elementAlign  The String representing the corner of 
3288         * the Overlay that should be aligned to the context element
3289         * @param {String} contextAlign  The corner of the context element 
3290         * that the elementAlign corner should stick to.
3291         */
3292         align: function (elementAlign, contextAlign) {
3293     
3294             var contextArgs = this.cfg.getProperty("context"),
3295                 me = this,
3296                 context,
3297                 element,
3298                 contextRegion;
3299     
3300     
3301             function doAlign(v, h) {
3302     
3303                 switch (elementAlign) {
3304     
3305                 case Overlay.TOP_LEFT:
3306     
3307                     me.moveTo(h, v);
3308     
3309                     break;
3310     
3311                 case Overlay.TOP_RIGHT:
3312     
3313                     me.moveTo((h - element.offsetWidth), v);
3314     
3315                     break;
3316     
3317                 case Overlay.BOTTOM_LEFT:
3318     
3319                     me.moveTo(h, (v - element.offsetHeight));
3320     
3321                     break;
3322     
3323                 case Overlay.BOTTOM_RIGHT:
3324     
3325                     me.moveTo((h - element.offsetWidth), 
3326                         (v - element.offsetHeight));
3327     
3328                     break;
3329     
3330                 }
3331     
3332             }
3333     
3334     
3335             if (contextArgs) {
3336             
3337                 context = contextArgs[0];
3338                 element = this.element;
3339                 me = this;
3340                 
3341                 if (! elementAlign) {
3342     
3343                     elementAlign = contextArgs[1];
3344     
3345                 }
3346                 
3347                 if (! contextAlign) {
3348     
3349                     contextAlign = contextArgs[2];
3350     
3351                 }
3352                 
3353                 if (element && context) {
3354     
3355                     contextRegion = Dom.getRegion(context);
3356                     
3357                     switch (contextAlign) {
3358     
3359                     case Overlay.TOP_LEFT:
3360     
3361                         doAlign(contextRegion.top, contextRegion.left);
3362     
3363                         break;
3364     
3365                     case Overlay.TOP_RIGHT:
3366     
3367                         doAlign(contextRegion.top, contextRegion.right);
3368     
3369                         break;
3370     
3371                     case Overlay.BOTTOM_LEFT:
3372     
3373                         doAlign(contextRegion.bottom, contextRegion.left);
3374     
3375                         break;
3376     
3377                     case Overlay.BOTTOM_RIGHT:
3378     
3379                         doAlign(contextRegion.bottom, contextRegion.right);
3380     
3381                         break;
3382     
3383                     }
3384     
3385                 }
3386     
3387             }
3388             
3389         },
3390         
3391         /**
3392         * The default event handler executed when the moveEvent is fired, if the 
3393         * "constraintoviewport" is set to true.
3394         * @method enforceConstraints
3395         * @param {String} type The CustomEvent type (usually the property name)
3396         * @param {Object[]} args The CustomEvent arguments. For configuration 
3397         * handlers, args[0] will equal the newly applied value for the property.
3398         * @param {Object} obj The scope object. For configuration handlers, 
3399         * this will usually equal the owner.
3400         */
3401         enforceConstraints: function (type, args, obj) {
3402     
3403             var pos = args[0],
3404                 x = pos[0],
3405                 y = pos[1],
3406                 offsetHeight = this.element.offsetHeight,
3407                 offsetWidth = this.element.offsetWidth,
3408                 viewPortWidth = Dom.getViewportWidth(),
3409                 viewPortHeight = Dom.getViewportHeight(),
3410                 scrollX = Dom.getDocumentScrollLeft(),
3411                 scrollY = Dom.getDocumentScrollTop(),
3412                 topConstraint = scrollY + 10,
3413                 leftConstraint = scrollX + 10,
3414                 bottomConstraint = scrollY + viewPortHeight - offsetHeight - 10,
3415                 rightConstraint = scrollX + viewPortWidth - offsetWidth - 10;
3416         
3417     
3418             if (x < leftConstraint) {
3419     
3420                 x = leftConstraint;
3421     
3422             } else if (x > rightConstraint) {
3423     
3424                 x = rightConstraint;
3425     
3426             }
3427             
3428             if (y < topConstraint) {
3429     
3430                 y = topConstraint;
3431     
3432             } else if (y > bottomConstraint) {
3433     
3434                 y = bottomConstraint;
3435     
3436             }
3437             
3438             this.cfg.setProperty("x", x, true);
3439             this.cfg.setProperty("y", y, true);
3440             this.cfg.setProperty("xy", [x, y], true);
3441     
3442         },
3443         
3444         /**
3445         * Centers the container in the viewport.
3446         * @method center
3447         */
3448         center: function () {
3449     
3450             var scrollX = Dom.getDocumentScrollLeft(),
3451                 scrollY = Dom.getDocumentScrollTop(),
3452     
3453                 viewPortWidth = Dom.getClientWidth(),
3454                 viewPortHeight = Dom.getClientHeight(),
3455                 elementWidth = this.element.offsetWidth,
3456                 elementHeight = this.element.offsetHeight,
3457                 x = (viewPortWidth / 2) - (elementWidth / 2) + scrollX,
3458                 y = (viewPortHeight / 2) - (elementHeight / 2) + scrollY;
3459             
3460             this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
3461             
3462             this.cfg.refireEvent("iframe");
3463     
3464         },
3465         
3466         /**
3467         * Synchronizes the Panel's "xy", "x", and "y" properties with the 
3468         * Panel's position in the DOM. This is primarily used to update  
3469         * position information during drag & drop.
3470         * @method syncPosition
3471         */
3472         syncPosition: function () {
3473     
3474             var pos = Dom.getXY(this.element);
3475     
3476             this.cfg.setProperty("x", pos[0], true);
3477             this.cfg.setProperty("y", pos[1], true);
3478             this.cfg.setProperty("xy", pos, true);
3479     
3480         },
3481         
3482         /**
3483         * Event handler fired when the resize monitor element is resized.
3484         * @method onDomResize
3485         * @param {DOMEvent} e The resize DOM event
3486         * @param {Object} obj The scope object
3487         */
3488         onDomResize: function (e, obj) {
3489     
3490             var me = this;
3491     
3492             Overlay.superclass.onDomResize.call(this, e, obj);
3493     
3494             setTimeout(function () {
3495                 me.syncPosition();
3496                 me.cfg.refireEvent("iframe");
3497                 me.cfg.refireEvent("context");
3498             }, 0);
3499     
3500         },
3502         /**
3503         * Places the Overlay on top of all other instances of 
3504         * YAHOO.widget.Overlay.
3505         * @method bringToTop
3506         */
3507         bringToTop: function() {
3508     
3509             var aOverlays = [],
3510                 oElement = this.element;
3511     
3512             function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
3513         
3514                 var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
3515         
3516                     sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
3517         
3518                     nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 
3519                         0 : parseInt(sZIndex1, 10),
3520         
3521                     nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 
3522                         0 : parseInt(sZIndex2, 10);
3523         
3524                 if (nZIndex1 > nZIndex2) {
3525         
3526                     return -1;
3527         
3528                 } else if (nZIndex1 < nZIndex2) {
3529         
3530                     return 1;
3531         
3532                 } else {
3533         
3534                     return 0;
3535         
3536                 }
3537         
3538             }
3539         
3540             function isOverlayElement(p_oElement) {
3541         
3542                 var oOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
3543                     Panel = YAHOO.widget.Panel;
3544             
3545                 if (oOverlay && !Dom.isAncestor(oElement, oOverlay)) {
3546                 
3547                     if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
3548         
3549                         aOverlays[aOverlays.length] = p_oElement.parentNode;
3550                     
3551                     }
3552                     else {
3553         
3554                         aOverlays[aOverlays.length] = p_oElement;
3555         
3556                     }
3557                 
3558                 }
3559             
3560             }
3561             
3562             Dom.getElementsBy(isOverlayElement, "DIV", document.body);
3563     
3564             aOverlays.sort(compareZIndexDesc);
3565             
3566             var oTopOverlay = aOverlays[0],
3567                 nTopZIndex;
3568             
3569             if (oTopOverlay) {
3570     
3571                 nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
3572     
3573                 if (!isNaN(nTopZIndex) && oTopOverlay != oElement) {
3574     
3575                     this.cfg.setProperty("zindex", 
3576                         (parseInt(nTopZIndex, 10) + 2));
3577     
3578                 }
3579             
3580             }
3581         
3582         },
3583         
3584         /**
3585         * Removes the Overlay element from the DOM and sets all child 
3586         * elements to null.
3587         * @method destroy
3588         */
3589         destroy: function () {
3590     
3591             if (this.iframe) {
3592     
3593                 this.iframe.parentNode.removeChild(this.iframe);
3594     
3595             }
3596         
3597             this.iframe = null;
3598         
3599             Overlay.windowResizeEvent.unsubscribe(
3600                 this.doCenterOnDOMEvent, this);
3601     
3602             Overlay.windowScrollEvent.unsubscribe(
3603                 this.doCenterOnDOMEvent, this);
3604         
3605             Overlay.superclass.destroy.call(this);
3606         },
3607         
3608         /**
3609         * Returns a String representation of the object.
3610         * @method toString
3611         * @return {String} The string representation of the Overlay.
3612         */
3613         toString: function () {
3614     
3615             return "Overlay " + this.id;
3616     
3617         }
3618     
3619     });
3620     
3621 }());
3622 (function () {
3623     
3624     /**
3625     * OverlayManager is used for maintaining the focus status of 
3626     * multiple Overlays.
3627     * @namespace YAHOO.widget
3628     * @namespace YAHOO.widget
3629     * @class OverlayManager
3630     * @constructor
3631     * @param {Array} overlays Optional. A collection of Overlays to register 
3632     * with the manager.
3633     * @param {Object} userConfig  The object literal representing the user 
3634     * configuration of the OverlayManager
3635     */
3636     YAHOO.widget.OverlayManager = function (userConfig) {
3637     
3638         this.init(userConfig);
3639     
3640     };
3643     var Overlay = YAHOO.widget.Overlay,
3644         Event = YAHOO.util.Event,
3645         Dom = YAHOO.util.Dom,
3646         Config = YAHOO.util.Config,
3647         CustomEvent = YAHOO.util.CustomEvent,
3648         OverlayManager = YAHOO.widget.OverlayManager;
3650     
3651     /**
3652     * The CSS class representing a focused Overlay
3653     * @property OverlayManager.CSS_FOCUSED
3654     * @static
3655     * @final
3656     * @type String
3657     */
3658     OverlayManager.CSS_FOCUSED = "focused";
3659     
3660     OverlayManager.prototype = {
3661     
3662         /**
3663         * The class's constructor function
3664         * @property contructor
3665         * @type Function
3666         */
3667         constructor: OverlayManager,
3668         
3669         /**
3670         * The array of Overlays that are currently registered
3671         * @property overlays
3672         * @type YAHOO.widget.Overlay[]
3673         */
3674         overlays: null,
3675         
3676         /**
3677         * Initializes the default configuration of the OverlayManager
3678         * @method initDefaultConfig
3679         */
3680         initDefaultConfig: function () {
3681         
3682             /**
3683             * The collection of registered Overlays in use by 
3684             * the OverlayManager
3685             * @config overlays
3686             * @type YAHOO.widget.Overlay[]
3687             * @default null
3688             */
3689             this.cfg.addProperty("overlays", { suppressEvent: true } );
3690         
3691             /**
3692             * The default DOM event that should be used to focus an Overlay
3693             * @config focusevent
3694             * @type String
3695             * @default "mousedown"
3696             */
3697             this.cfg.addProperty("focusevent", { value: "mousedown" } );
3698         
3699         },
3700         
3701         /**
3702         * Initializes the OverlayManager
3703         * @method init
3704         * @param {Overlay[]} overlays Optional. A collection of Overlays to 
3705         * register with the manager.
3706         * @param {Object} userConfig  The object literal representing the user 
3707         * configuration of the OverlayManager
3708         */
3709         init: function (userConfig) {
3711             /**
3712             * The OverlayManager's Config object used for monitoring 
3713             * configuration properties.
3714             * @property cfg
3715             * @type Config
3716             */
3717             this.cfg = new Config(this);
3718         
3719             this.initDefaultConfig();
3720         
3721             if (userConfig) {
3722                 this.cfg.applyConfig(userConfig, true);
3723             }
3724             this.cfg.fireQueue();
3725         
3726             /**
3727             * The currently activated Overlay
3728             * @property activeOverlay
3729             * @private
3730             * @type YAHOO.widget.Overlay
3731             */
3732             var activeOverlay = null;
3733         
3734             /**
3735             * Returns the currently focused Overlay
3736             * @method getActive
3737             * @return {Overlay} The currently focused Overlay
3738             */
3739             this.getActive = function () {
3740                 return activeOverlay;
3741             };
3742         
3743             /**
3744             * Focuses the specified Overlay
3745             * @method focus
3746             * @param {Overlay} overlay The Overlay to focus
3747             * @param {String} overlay The id of the Overlay to focus
3748             */
3749             this.focus = function (overlay) {
3750         
3751                 var o = this.find(overlay);
3752         
3753                 if (o) {
3754         
3755                     if (activeOverlay != o) {
3756         
3757                         if (activeOverlay) {
3758         
3759                             activeOverlay.blur();
3760         
3761                         }
3762         
3763                         this.bringToTop(o);
3764                         
3765                         activeOverlay = o;
3766         
3767                         Dom.addClass(activeOverlay.element, 
3768                             OverlayManager.CSS_FOCUSED);
3770                         o.focusEvent.fire();
3771                         
3772                     }
3773         
3774                 }
3775         
3776             };
3777         
3778             /**
3779             * Removes the specified Overlay from the manager
3780             * @method remove
3781             * @param {Overlay} overlay The Overlay to remove
3782             * @param {String} overlay The id of the Overlay to remove
3783             */
3784             this.remove = function (overlay) {
3785     
3786                 var o = this.find(overlay),
3787                     originalZ;
3788         
3789                 if (o) {
3791                     if (activeOverlay == o) {
3792                     
3793                         activeOverlay = null;
3794                     
3795                     }
3797                     originalZ = Dom.getStyle(o.element, "zIndex");
3799                     o.cfg.setProperty("zIndex", -1000, true);
3801                     this.overlays.sort(this.compareZIndexDesc);
3803                     this.overlays = 
3804                         this.overlays.slice(0, (this.overlays.length - 1));
3805         
3806                     o.hideEvent.unsubscribe(o.blur);
3807                     o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
3808         
3809                     if (o.element) {
3810         
3811                         Event.removeListener(o.element, 
3812                             this.cfg.getProperty("focusevent"), 
3813                             this._onOverlayElementFocus);
3814         
3815                     }
3816         
3817                     o.cfg.setProperty("zIndex", originalZ, true);
3818                     o.cfg.setProperty("manager", null);
3819         
3820                     o.focusEvent.unsubscribeAll();
3821                     o.blurEvent.unsubscribeAll();
3822         
3823                     o.focusEvent = null;
3824                     o.blurEvent = null;
3825         
3826                     o.focus = null;
3827                     o.blur = null;
3828                 }
3830             };
3831         
3832             /**
3833             * Removes focus from all registered Overlays in the manager
3834             * @method blurAll
3835             */
3836             this.blurAll = function () {
3837     
3838                 var nOverlays = this.overlays.length,
3839                     i;
3841                 if (nOverlays > 0) {
3843                     i = nOverlays - 1;
3844                     
3845                     do {
3847                         this.overlays[i].blur();                    
3848                     
3849                     }
3850                     while(i--);
3851                 
3852                 }
3853     
3854             };
3855         
3856         
3857             this._onOverlayBlur = function (p_sType, p_aArgs) {
3859                 activeOverlay = null;
3861             };
3862         
3863         
3864             var overlays = this.cfg.getProperty("overlays");
3865         
3866             if (! this.overlays) {
3867                 this.overlays = [];
3868             }
3869         
3870             if (overlays) {
3871                 this.register(overlays);
3872                 this.overlays.sort(this.compareZIndexDesc);
3873             }
3874         },
3875         
3876         
3877         /**
3878         * @method _onOverlayElementFocus
3879         * @description Event handler for the DOM event that is used to focus 
3880         * the Overlay instance as specified by the "focusevent" 
3881         * configuration property.
3882         * @private
3883         * @param {Event} p_oEvent Object representing the DOM event 
3884         * object passed back by the event utility (Event).
3885         */
3886         _onOverlayElementFocus: function (p_oEvent) {
3887         
3888             var oTarget = Event.getTarget(p_oEvent),
3889                 oClose = this.close;
3890         
3891             
3892             if (oClose && (oTarget == oClose || 
3893                     Dom.isAncestor(oClose, oTarget))) {
3894             
3895                 this.blur();
3896             
3897             }
3898             else {
3899             
3900                 this.focus();
3901             
3902             }
3903         
3904         },
3905         
3906         
3907         /**
3908         * @method _onOverlayDestroy
3909         * @description "destroy" event handler for the Overlay.
3910         * @private
3911         * @param {String} p_sType String representing the name of the event  
3912         * that was fired.
3913         * @param {Array} p_aArgs Array of arguments sent when the event 
3914         * was fired.
3915         * @param {Overlay} p_oOverlay Object representing the menu that 
3916         * fired the event.
3917         */
3918         _onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
3919         
3920             this.remove(p_oOverlay);
3921         
3922         },
3923         
3924         /**
3925         * Registers an Overlay or an array of Overlays with the manager. Upon 
3926         * registration, the Overlay receives functions for focus and blur, 
3927         * along with CustomEvents for each.
3928         * @method register
3929         * @param {Overlay} overlay  An Overlay to register with the manager.
3930         * @param {Overlay[]} overlay  An array of Overlays to register with 
3931         * the manager.
3932         * @return {Boolean} True if any Overlays are registered.
3933         */
3934         register: function (overlay) {
3935         
3936             var mgr = this,
3937                 zIndex,
3938                 regcount,
3939                 i,
3940                 nOverlays;
3941         
3942             if (overlay instanceof Overlay) {
3944                 overlay.cfg.addProperty("manager", { value: this } );
3945         
3946                 overlay.focusEvent = overlay.createEvent("focus");
3947                 overlay.focusEvent.signature = CustomEvent.LIST;
3948         
3949                 overlay.blurEvent = overlay.createEvent("blur");
3950                 overlay.blurEvent.signature = CustomEvent.LIST;
3951         
3952                 overlay.focus = function () {
3953                     mgr.focus(this);
3954                 };
3955         
3956                 overlay.blur = function () {
3957     
3958                     if (mgr.getActive() == this) {
3960                         Dom.removeClass(this.element, 
3961                             OverlayManager.CSS_FOCUSED);
3963                         this.blurEvent.fire();
3965                     }
3967                 };
3968         
3969                 overlay.blurEvent.subscribe(mgr._onOverlayBlur);
3970         
3971                 overlay.hideEvent.subscribe(overlay.blur);
3972                 
3973                 overlay.destroyEvent.subscribe(this._onOverlayDestroy, 
3974                     overlay, this);
3975         
3976                 Event.on(overlay.element, this.cfg.getProperty("focusevent"), 
3977                     this._onOverlayElementFocus, null, overlay);
3978         
3979                 zIndex = Dom.getStyle(overlay.element, "zIndex");
3981                 if (!isNaN(zIndex)) {
3983                     overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
3985                 } else {
3987                     overlay.cfg.setProperty("zIndex", 0);
3989                 }
3990         
3992                 this.overlays.push(overlay);
3994                 this.bringToTop(overlay);
3996                 return true;
3998             } else if (overlay instanceof Array) {
4000                 regcount = 0;
4001                 nOverlays = overlay.length;
4003                 for (i = 0; i < nOverlays; i++) {
4005                     if (this.register(overlay[i])) {
4007                         regcount++;
4009                     }
4010                 }
4012                 if (regcount > 0) {
4014                     return true;
4016                 }
4018             } else {
4020                 return false;
4022             }
4024         },
4026         /**
4027         * Places the specified Overlay instance on top of all other 
4028         * Overlay instances.
4029         * @method bringToTop
4030         * @param {YAHOO.widget.Overlay} p_oOverlay Object representing an 
4031         * Overlay instance.
4032         * @param {String} p_oOverlay String representing the id of an 
4033         * Overlay instance.
4034         */        
4035         bringToTop: function (p_oOverlay) {
4037             var oOverlay = this.find(p_oOverlay),
4038                 nTopZIndex,
4039                 oTopOverlay,
4040                 aOverlays;
4042             if (oOverlay) {
4044                 aOverlays = this.overlays;
4046                 aOverlays.sort(this.compareZIndexDesc);
4047                 
4048                 oTopOverlay = aOverlays[0];
4049                 
4050                 if (oTopOverlay) {
4052                     nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
4053     
4054                     if (!isNaN(nTopZIndex) && oTopOverlay != oOverlay) {
4055     
4056                         oOverlay.cfg.setProperty("zIndex", 
4057                             (parseInt(nTopZIndex, 10) + 2));
4058     
4059                     }
4060     
4061                     aOverlays.sort(this.compareZIndexDesc);
4062                 
4063                 }
4065             }
4066         
4067         },
4068         
4069         /**
4070         * Attempts to locate an Overlay by instance or ID.
4071         * @method find
4072         * @param {Overlay} overlay  An Overlay to locate within the manager
4073         * @param {String} overlay  An Overlay id to locate within the manager
4074         * @return {Overlay} The requested Overlay, if found, or null if it 
4075         * cannot be located.
4076         */
4077         find: function (overlay) {
4078         
4079             var aOverlays = this.overlays,
4080                 nOverlays = aOverlays.length,
4081                 i;
4083             if (nOverlays > 0) {
4085                 i = nOverlays - 1;
4087                 if (overlay instanceof Overlay) {
4089                     do {
4091                         if (aOverlays[i] == overlay) {
4093                             return aOverlays[i];
4095                         }
4096                     
4097                     }
4098                     while(i--);
4100                 } else if (typeof overlay == "string") {
4102                     do {
4104                         if (aOverlays[i].id == overlay) {
4106                             return aOverlays[i];
4108                         }
4110                     }
4111                     while(i--);
4113                 }
4115                 return null;
4116             
4117             }
4119         },
4120         
4121         /**
4122         * Used for sorting the manager's Overlays by z-index.
4123         * @method compareZIndexDesc
4124         * @private
4125         * @return {Number} 0, 1, or -1, depending on where the Overlay should 
4126         * fall in the stacking order.
4127         */
4128         compareZIndexDesc: function (o1, o2) {
4129     
4130             var zIndex1 = o1.cfg.getProperty("zIndex"),
4131                 zIndex2 = o2.cfg.getProperty("zIndex");
4132         
4133             if (zIndex1 > zIndex2) {
4134                 return -1;
4135             } else if (zIndex1 < zIndex2) {
4136                 return 1;
4137             } else {
4138                 return 0;
4139             }
4140         },
4141         
4142         /**
4143         * Shows all Overlays in the manager.
4144         * @method showAll
4145         */
4146         showAll: function () {
4147         
4148             var aOverlays = this.overlays,
4149                 nOverlays = aOverlays.length,
4150                 i;
4152             if (nOverlays > 0) {
4153             
4154                 i = nOverlays - 1;
4155                 
4156                 do {
4158                     aOverlays[i].show();
4159                 
4160                 }
4161                 while(i--);
4162             
4163             }
4164     
4165         },
4166         
4167         /**
4168         * Hides all Overlays in the manager.
4169         * @method hideAll
4170         */
4171         hideAll: function () {
4172         
4173             var aOverlays = this.overlays,
4174                 nOverlays = aOverlays.length,
4175                 i;
4177             if (nOverlays > 0) {
4178             
4179                 i = nOverlays - 1;
4180                 
4181                 do {
4183                     aOverlays[i].hide();
4184                 
4185                 }
4186                 while(i--);
4187             
4188             }
4189     
4190         },
4191         
4192         /**
4193         * Returns a string representation of the object.
4194         * @method toString
4195         * @return {String} The string representation of the OverlayManager
4196         */
4197         toString: function () {
4198             return "OverlayManager";
4199         }
4200     
4201     };
4203 }());
4204 (function () {
4206     /**
4207     * Tooltip is an implementation of Overlay that behaves like an OS tooltip, 
4208     * displaying when the user mouses over a particular element, and 
4209     * disappearing on mouse out.
4210     * @namespace YAHOO.widget
4211     * @class Tooltip
4212     * @extends YAHOO.widget.Overlay
4213     * @constructor
4214     * @param {String} el The element ID representing the Tooltip <em>OR</em>
4215     * @param {HTMLElement} el The element representing the Tooltip
4216     * @param {Object} userConfig The configuration object literal containing 
4217     * the configuration that should be set for this Overlay. See configuration 
4218     * documentation for more details.
4219     */
4220     YAHOO.widget.Tooltip = function (el, userConfig) {
4221     
4222         YAHOO.widget.Tooltip.superclass.constructor.call(this, el, userConfig);
4223     
4224     };
4227     var Lang = YAHOO.lang,
4228         Event = YAHOO.util.Event,
4229         Dom = YAHOO.util.Dom,
4230         Tooltip = YAHOO.widget.Tooltip,
4231     
4232         m_oShadowTemplate,
4233         
4234         /**
4235         * Constant representing the Tooltip's configuration properties
4236         * @property DEFAULT_CONFIG
4237         * @private
4238         * @final
4239         * @type Object
4240         */
4241         DEFAULT_CONFIG = {
4242         
4243             "PREVENT_OVERLAP": { 
4244                 key: "preventoverlap", 
4245                 value: true, 
4246                 validator: Lang.isBoolean, 
4247                 supercedes: ["x", "y", "xy"] 
4248             },
4249         
4250             "SHOW_DELAY": { 
4251                 key: "showdelay", 
4252                 value: 200, 
4253                 validator: Lang.isNumber 
4254             }, 
4255         
4256             "AUTO_DISMISS_DELAY": { 
4257                 key: "autodismissdelay", 
4258                 value: 5000, 
4259                 validator: Lang.isNumber 
4260             }, 
4261         
4262             "HIDE_DELAY": { 
4263                 key: "hidedelay", 
4264                 value: 250, 
4265                 validator: Lang.isNumber 
4266             }, 
4267         
4268             "TEXT": { 
4269                 key: "text", 
4270                 suppressEvent: true 
4271             }, 
4272         
4273             "CONTAINER": { 
4274                 key: "container"
4275             }
4276         
4277         };
4279     
4280     /**
4281     * Constant representing the Tooltip CSS class
4282     * @property YAHOO.widget.Tooltip.CSS_TOOLTIP
4283     * @static
4284     * @final
4285     * @type String
4286     */
4287     Tooltip.CSS_TOOLTIP = "yui-tt";
4290     /* 
4291         "hide" event handler that sets a Tooltip instance's "width"
4292         configuration property back to its original value before 
4293         "setWidthToOffsetWidth" was called.
4294     */
4295     
4296     function restoreOriginalWidth(p_sType, p_aArgs, p_oObject) {
4298         var sOriginalWidth = p_oObject[0],
4299             sNewWidth = p_oObject[1],
4300             oConfig = this.cfg,
4301             sCurrentWidth = oConfig.getProperty("width");
4303         if (sCurrentWidth == sNewWidth) {
4304             
4305             oConfig.setProperty("width", sOriginalWidth);
4306         
4307         }
4309         this.unsubscribe("hide", this._onHide, p_oObject);
4310     
4311     }
4313     /* 
4314         "beforeShow" event handler that sets a Tooltip instance's "width"
4315         configuration property to the value of its root HTML 
4316         elements's offsetWidth
4317     */
4319     function setWidthToOffsetWidth(p_sType, p_aArgs) {
4321         var oBody = document.body,
4322             oConfig = this.cfg,
4323             sOriginalWidth = oConfig.getProperty("width"),
4324             sNewWidth,
4325             oClone;
4327         
4328         if ((!sOriginalWidth || sOriginalWidth == "auto") && 
4329             (oConfig.getProperty("container") != oBody || 
4330             oConfig.getProperty("x") >= Dom.getViewportWidth() || 
4331             oConfig.getProperty("y") >= Dom.getViewportHeight())) {
4333             oClone = this.element.cloneNode(true);
4334             oClone.style.visibility = "hidden";
4335             oClone.style.top = "0px";
4336             oClone.style.left = "0px";
4337             
4338             oBody.appendChild(oClone);
4340             sNewWidth = (oClone.offsetWidth + "px");
4341             
4342             oBody.removeChild(oClone);
4343             
4344             oClone = null;
4346             oConfig.setProperty("width", sNewWidth);
4347             
4348             oConfig.refireEvent("xy");
4349             
4350             this.subscribe("hide", restoreOriginalWidth, 
4351                 [(sOriginalWidth || ""), sNewWidth]);
4352         
4353         }
4355     }
4358     // "onDOMReady" that renders the ToolTip
4360     function onDOMReady(p_sType, p_aArgs, p_oObject) {
4361     
4362         this.render(p_oObject);
4363     
4364     }
4367     //  "init" event handler that automatically renders the Tooltip
4369     function onInit() {
4371         Event.onDOMReady(onDOMReady, this.cfg.getProperty("container"), this);
4373     }
4375     
4376     YAHOO.extend(Tooltip, YAHOO.widget.Overlay, { 
4377     
4378         /**
4379         * The Tooltip initialization method. This method is automatically 
4380         * called by the constructor. A Tooltip is automatically rendered by 
4381         * the init method, and it also is set to be invisible by default, 
4382         * and constrained to viewport by default as well.
4383         * @method init
4384         * @param {String} el The element ID representing the Tooltip <em>OR</em>
4385         * @param {HTMLElement} el The element representing the Tooltip
4386         * @param {Object} userConfig The configuration object literal 
4387         * containing the configuration that should be set for this Tooltip. 
4388         * See configuration documentation for more details.
4389         */
4390         init: function (el, userConfig) {
4391     
4392             this.logger = new YAHOO.widget.LogWriter(this.toString());
4393     
4394             Tooltip.superclass.init.call(this, el);
4395     
4396             this.beforeInitEvent.fire(Tooltip);
4397     
4398             Dom.addClass(this.element, Tooltip.CSS_TOOLTIP);
4399     
4400             if (userConfig) {
4402                 this.cfg.applyConfig(userConfig, true);
4404             }
4405     
4406             this.cfg.queueProperty("visible", false);
4407             this.cfg.queueProperty("constraintoviewport", true);
4408     
4409             this.setBody("");
4411             this.subscribe("beforeShow", setWidthToOffsetWidth);
4412             this.subscribe("init", onInit);
4413             this.subscribe("render", this.onRender);
4414     
4415             this.initEvent.fire(Tooltip);
4417         },
4418         
4419         /**
4420         * Initializes the class's configurable properties which can be 
4421         * changed using the Overlay's Config object (cfg).
4422         * @method initDefaultConfig
4423         */
4424         initDefaultConfig: function () {
4426             Tooltip.superclass.initDefaultConfig.call(this);
4427         
4428             /**
4429             * Specifies whether the Tooltip should be kept from overlapping 
4430             * its context element.
4431             * @config preventoverlap
4432             * @type Boolean
4433             * @default true
4434             */
4435             this.cfg.addProperty(DEFAULT_CONFIG.PREVENT_OVERLAP.key, {
4436                 value: DEFAULT_CONFIG.PREVENT_OVERLAP.value, 
4437                 validator: DEFAULT_CONFIG.PREVENT_OVERLAP.validator, 
4438                 supercedes: DEFAULT_CONFIG.PREVENT_OVERLAP.supercedes
4439             });
4440         
4441             /**
4442             * The number of milliseconds to wait before showing a Tooltip 
4443             * on mouseover.
4444             * @config showdelay
4445             * @type Number
4446             * @default 200
4447             */
4448             this.cfg.addProperty(DEFAULT_CONFIG.SHOW_DELAY.key, {
4449                 handler: this.configShowDelay,
4450                 value: 200, 
4451                 validator: DEFAULT_CONFIG.SHOW_DELAY.validator
4452             });
4453         
4454             /**
4455             * The number of milliseconds to wait before automatically 
4456             * dismissing a Tooltip after the mouse has been resting on the 
4457             * context element.
4458             * @config autodismissdelay
4459             * @type Number
4460             * @default 5000
4461             */
4462             this.cfg.addProperty(DEFAULT_CONFIG.AUTO_DISMISS_DELAY.key, {
4463                 handler: this.configAutoDismissDelay,
4464                 value: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.value,
4465                 validator: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.validator
4466             });
4467         
4468             /**
4469             * The number of milliseconds to wait before hiding a Tooltip 
4470             * on mouseover.
4471             * @config hidedelay
4472             * @type Number
4473             * @default 250
4474             */
4475             this.cfg.addProperty(DEFAULT_CONFIG.HIDE_DELAY.key, {
4476                 handler: this.configHideDelay,
4477                 value: DEFAULT_CONFIG.HIDE_DELAY.value, 
4478                 validator: DEFAULT_CONFIG.HIDE_DELAY.validator
4479             });
4480         
4481             /**
4482             * Specifies the Tooltip's text.
4483             * @config text
4484             * @type String
4485             * @default null
4486             */
4487             this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, {
4488                 handler: this.configText,
4489                 suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent
4490             });
4492             /**
4493             * Specifies the container element that the Tooltip's markup 
4494             * should be rendered into.
4495             * @config container
4496             * @type HTMLElement/String
4497             * @default document.body
4498             */
4499             this.cfg.addProperty(DEFAULT_CONFIG.CONTAINER.key, {
4500                 handler: this.configContainer,
4501                 value: document.body
4502             });
4503         
4504             /**
4505             * Specifies the element or elements that the Tooltip should be 
4506             * anchored to on mouseover.
4507             * @config context
4508             * @type HTMLElement[]/String[]
4509             * @default null
4510             */ 
4512             /**
4513             * String representing the width of the Tooltip.  <em>Please note:
4514             * </em> As of version 2.3 if either no value or a value of "auto" 
4515             * is specified, and the Toolip's "container" configuration property
4516             * is set to something other than <code>document.body</code> or 
4517             * its "context" element resides outside the immediately visible 
4518             * portion of the document, the width of the Tooltip will be 
4519             * calculated based on the offsetWidth of its root HTML and set just 
4520             * before it is made visible.  The original value will be 
4521             * restored when the Tooltip is hidden. This ensures the Tooltip is 
4522             * rendered at a usable width.  For more information see 
4523             * SourceForge bug #1685496 and SourceForge 
4524             * bug #1735423.
4525             * @config width
4526             * @type String
4527             * @default null
4528             */
4529         
4530         },
4531         
4532         // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
4533         
4534         /**
4535         * The default event handler fired when the "text" property is changed.
4536         * @method configText
4537         * @param {String} type The CustomEvent type (usually the property name)
4538         * @param {Object[]} args The CustomEvent arguments. For configuration 
4539         * handlers, args[0] will equal the newly applied value for the property.
4540         * @param {Object} obj The scope object. For configuration handlers, 
4541         * this will usually equal the owner.
4542         */
4543         configText: function (type, args, obj) {
4544             var text = args[0];
4545             if (text) {
4546                 this.setBody(text);
4547             }
4548         },
4549         
4550         /**
4551         * The default event handler fired when the "container" property 
4552         * is changed.
4553         * @method configContainer
4554         * @param {String} type The CustomEvent type (usually the property name)
4555         * @param {Object[]} args The CustomEvent arguments. For 
4556         * configuration handlers, args[0] will equal the newly applied value 
4557         * for the property.
4558         * @param {Object} obj The scope object. For configuration handlers,
4559         * this will usually equal the owner.
4560         */
4561         configContainer: function (type, args, obj) {
4563             var container = args[0];
4565             if (typeof container == 'string') {
4567                 this.cfg.setProperty("container", 
4568                     document.getElementById(container), true);
4570             }
4572         },
4573         
4574         /**
4575         * @method _removeEventListeners
4576         * @description Removes all of the DOM event handlers from the HTML
4577         *  element(s) that trigger the display of the tooltip.
4578         * @protected
4579         */
4580         _removeEventListeners: function () {
4581         
4582             var aElements = this._context,
4583                 nElements,
4584                 oElement,
4585                 i;
4586         
4587             
4588             if (aElements) {
4589         
4590                 nElements = aElements.length;
4591                 
4592                 if (nElements > 0) {
4593                 
4594                     i = nElements - 1;
4595                     
4596                     do {
4597         
4598                         oElement = aElements[i];
4599         
4600                         Event.removeListener(oElement, "mouseover", 
4601                             this.onContextMouseOver);
4603                         Event.removeListener(oElement, "mousemove", 
4604                             this.onContextMouseMove);
4606                         Event.removeListener(oElement, "mouseout", 
4607                             this.onContextMouseOut);
4608                     
4609                     }
4610                     while (i--);
4611                 
4612                 }
4613         
4614             }
4615         
4616         },
4617         
4618         /**
4619         * The default event handler fired when the "context" property 
4620         * is changed.
4621         * @method configContext
4622         * @param {String} type The CustomEvent type (usually the property name)
4623         * @param {Object[]} args The CustomEvent arguments. For configuration 
4624         * handlers, args[0] will equal the newly applied value for the property.
4625         * @param {Object} obj The scope object. For configuration handlers,
4626         * this will usually equal the owner.
4627         */
4628         configContext: function (type, args, obj) {
4629         
4630             var context = args[0],
4631                 aElements,
4632                 nElements,
4633                 oElement,
4634                 i;
4635             
4636         
4637             if (context) {
4638         
4639                 // Normalize parameter into an array
4640                 if (! (context instanceof Array)) {
4642                     if (typeof context == "string") {
4644                         this.cfg.setProperty("context", 
4645                             [document.getElementById(context)], true);
4647                     } else { // Assuming this is an element
4649                         this.cfg.setProperty("context", [context], true);
4651                     }
4653                     context = this.cfg.getProperty("context");
4655                 }
4656         
4657         
4658                 // Remove any existing mouseover/mouseout listeners
4659                 this._removeEventListeners();
4660         
4661                 // Add mouseover/mouseout listeners to context elements
4662                 this._context = context;
4663         
4664                 aElements = this._context;
4665                 
4666                 if (aElements) {
4667             
4668                     nElements = aElements.length;
4669                     
4670                     if (nElements > 0) {
4671                     
4672                         i = nElements - 1;
4673                         
4674                         do {
4675             
4676                             oElement = aElements[i];
4677             
4678                             Event.on(oElement, "mouseover", 
4679                                 this.onContextMouseOver, this);
4681                             Event.on(oElement, "mousemove", 
4682                                 this.onContextMouseMove, this);
4684                             Event.on(oElement, "mouseout", 
4685                                 this.onContextMouseOut, this);
4686                         
4687                         }
4688                         while (i--);
4689                     
4690                     }
4691             
4692                 }
4693         
4694             }
4695         },
4696         
4697         // END BUILT-IN PROPERTY EVENT HANDLERS //
4698         
4699         // BEGIN BUILT-IN DOM EVENT HANDLERS //
4700         
4701         /**
4702         * The default event handler fired when the user moves the mouse while 
4703         * over the context element.
4704         * @method onContextMouseMove
4705         * @param {DOMEvent} e The current DOM event
4706         * @param {Object} obj The object argument
4707         */
4708         onContextMouseMove: function (e, obj) {
4709             obj.pageX = Event.getPageX(e);
4710             obj.pageY = Event.getPageY(e);
4711         
4712         },
4713         
4714         /**
4715         * The default event handler fired when the user mouses over the 
4716         * context element.
4717         * @method onContextMouseOver
4718         * @param {DOMEvent} e The current DOM event
4719         * @param {Object} obj The object argument
4720         */
4721         onContextMouseOver: function (e, obj) {
4722         
4723             var context = this;
4724         
4725             if (obj.hideProcId) {
4727                 clearTimeout(obj.hideProcId);
4729                 obj.logger.log("Clearing hide timer: " + 
4730                     obj.hideProcId, "time");
4732                 obj.hideProcId = null;
4734             }
4735         
4736             Event.on(context, "mousemove", obj.onContextMouseMove, obj);
4737         
4738             if (context.title) {
4739                 obj._tempTitle = context.title;
4740                 context.title = "";
4741             }
4742         
4743             /**
4744             * The unique process ID associated with the thread responsible 
4745             * for showing the Tooltip.
4746             * @type int
4747             */
4748             obj.showProcId = obj.doShow(e, context);
4749             obj.logger.log("Setting show tooltip timeout: " + 
4750                 obj.showProcId, "time");
4752         },
4753         
4754         /**
4755         * The default event handler fired when the user mouses out of 
4756         * the context element.
4757         * @method onContextMouseOut
4758         * @param {DOMEvent} e The current DOM event
4759         * @param {Object} obj The object argument
4760         */
4761         onContextMouseOut: function (e, obj) {
4762             var el = this;
4763         
4764             if (obj._tempTitle) {
4765                 el.title = obj._tempTitle;
4766                 obj._tempTitle = null;
4767             }
4768         
4769             if (obj.showProcId) {
4770                 clearTimeout(obj.showProcId);
4771                 obj.logger.log("Clearing show timer: " + 
4772                     obj.showProcId, "time");
4773                 obj.showProcId = null;
4774             }
4775         
4776             if (obj.hideProcId) {
4777                 clearTimeout(obj.hideProcId);
4778                 obj.logger.log("Clearing hide timer: " + 
4779                     obj.hideProcId, "time");
4780                 obj.hideProcId = null;
4781             }
4782         
4783         
4784             obj.hideProcId = setTimeout(function () {
4785                 obj.hide();
4786     
4787             }, obj.cfg.getProperty("hidedelay"));
4788     
4789         },
4790         
4791         // END BUILT-IN DOM EVENT HANDLERS //
4792         
4793         /**
4794         * Processes the showing of the Tooltip by setting the timeout delay 
4795         * and offset of the Tooltip.
4796         * @method doShow
4797         * @param {DOMEvent} e The current DOM event
4798         * @return {Number} The process ID of the timeout function associated 
4799         * with doShow
4800         */
4801         doShow: function (e, context) {
4802         
4803             var yOffset = 25,
4804                 me = this;
4805         
4806             if (YAHOO.env.ua.opera && context.tagName && 
4807                 context.tagName.toUpperCase() == "A") {
4809                 yOffset += 12;
4811             }
4812         
4813             return setTimeout(function () {
4814         
4815                 if (me._tempTitle) {
4816                     me.setBody(me._tempTitle);
4817                 } else {
4818                     me.cfg.refireEvent("text");
4819                 }
4820         
4821                 me.logger.log("Show tooltip", "time");
4822                 me.moveTo(me.pageX, me.pageY + yOffset);
4824                 if (me.cfg.getProperty("preventoverlap")) {
4825                     me.preventOverlap(me.pageX, me.pageY);
4826                 }
4827         
4828                 Event.removeListener(context, "mousemove", 
4829                     me.onContextMouseMove);
4830         
4831                 me.show();
4832                 me.hideProcId = me.doHide();
4834                 me.logger.log("Hide tooltip time active: " +
4835                     me.hideProcId, "time");
4837             }, this.cfg.getProperty("showdelay"));
4838         
4839         },
4840         
4841         /**
4842         * Sets the timeout for the auto-dismiss delay, which by default is 5 
4843         * seconds, meaning that a tooltip will automatically dismiss itself 
4844         * after 5 seconds of being displayed.
4845         * @method doHide
4846         */
4847         doHide: function () {
4848         
4849             var me = this;
4850         
4851             me.logger.log("Setting hide tooltip timeout", "time");
4852         
4853             return setTimeout(function () {
4854         
4855                 me.logger.log("Hide tooltip", "time");
4856                 me.hide();
4857         
4858             }, this.cfg.getProperty("autodismissdelay"));
4859         
4860         },
4861         
4862         /**
4863         * Fired when the Tooltip is moved, this event handler is used to 
4864         * prevent the Tooltip from overlapping with its context element.
4865         * @method preventOverlay
4866         * @param {Number} pageX The x coordinate position of the mouse pointer
4867         * @param {Number} pageY The y coordinate position of the mouse pointer
4868         */
4869         preventOverlap: function (pageX, pageY) {
4870         
4871             var height = this.element.offsetHeight,
4872                 mousePoint = new YAHOO.util.Point(pageX, pageY),
4873                 elementRegion = Dom.getRegion(this.element);
4874         
4875             elementRegion.top -= 5;
4876             elementRegion.left -= 5;
4877             elementRegion.right += 5;
4878             elementRegion.bottom += 5;
4879         
4880             this.logger.log("context " + elementRegion, "ttip");
4881             this.logger.log("mouse " + mousePoint, "ttip");
4882         
4883             if (elementRegion.contains(mousePoint)) {
4884                 this.logger.log("OVERLAP", "warn");
4885                 this.cfg.setProperty("y", (pageY - height - 5));
4886             }
4887         },
4890         /**
4891         * @method onRender
4892         * @description "render" event handler for the Tooltip.
4893         * @param {String} p_sType String representing the name of the event  
4894         * that was fired.
4895         * @param {Array} p_aArgs Array of arguments sent when the event 
4896         * was fired.
4897         */
4898         onRender: function (p_sType, p_aArgs) {
4899     
4900             function sizeShadow() {
4901     
4902                 var oElement = this.element,
4903                     oShadow = this._shadow;
4904             
4905                 if (oShadow) {
4906             
4907                     oShadow.style.width = (oElement.offsetWidth + 6) + "px";
4908                     oShadow.style.height = (oElement.offsetHeight + 1) + "px"; 
4909             
4910                 }
4911             
4912             }
4915             function addShadowVisibleClass() {
4916             
4917                 Dom.addClass(this._shadow, "yui-tt-shadow-visible");
4918             
4919             }
4920             
4922             function removeShadowVisibleClass() {
4923         
4924                 Dom.removeClass(this._shadow, "yui-tt-shadow-visible");
4925             
4926             }
4927     
4928     
4929             function createShadow() {
4930     
4931                 var oShadow = this._shadow,
4932                     oElement,
4933                     Module,
4934                     nIE,
4935                     me;
4936     
4937                 if (!oShadow) {
4938     
4939                     oElement = this.element;
4940                     Module = YAHOO.widget.Module;
4941                     nIE = YAHOO.env.ua.ie;
4942                     me = this;
4943     
4944                     if (!m_oShadowTemplate) {
4945         
4946                         m_oShadowTemplate = document.createElement("div");
4947                         m_oShadowTemplate.className = "yui-tt-shadow";
4948                     
4949                     }
4950         
4951                     oShadow = m_oShadowTemplate.cloneNode(false);
4952         
4953                     oElement.appendChild(oShadow);
4954                     
4955                     this._shadow = oShadow;
4956     
4957                     addShadowVisibleClass.call(this);
4958         
4959                     this.subscribe("beforeShow", addShadowVisibleClass);
4960                     this.subscribe("beforeHide", removeShadowVisibleClass);
4962                     if (nIE == 6 || 
4963                         (nIE == 7 && document.compatMode == "BackCompat")) {
4964                 
4965                         window.setTimeout(function () { 
4966         
4967                             sizeShadow.call(me); 
4968         
4969                         }, 0);
4970     
4971                         this.cfg.subscribeToConfigEvent("width", sizeShadow);
4972                         this.cfg.subscribeToConfigEvent("height", sizeShadow);
4973                         this.subscribe("changeContent", sizeShadow);
4974     
4975                         Module.textResizeEvent.subscribe(sizeShadow, 
4976                                                             this, true);
4977                         
4978                         this.subscribe("destroy", function () {
4979                         
4980                             Module.textResizeEvent.unsubscribe(sizeShadow, 
4981                                                                     this);
4982                         
4983                         });
4984                 
4985                     }
4986                 
4987                 }
4988     
4989             }
4990     
4991     
4992             function onBeforeShow() {
4993             
4994                 createShadow.call(this);
4995     
4996                 this.unsubscribe("beforeShow", onBeforeShow);
4997             
4998             }
4999     
5000     
5001             if (this.cfg.getProperty("visible")) {
5002     
5003                 createShadow.call(this);
5004             
5005             }
5006             else {
5007     
5008                 this.subscribe("beforeShow", onBeforeShow);
5009             
5010             }
5011         
5012         },
5013         
5014         /**
5015         * Removes the Tooltip element from the DOM and sets all child 
5016         * elements to null.
5017         * @method destroy
5018         */
5019         destroy: function () {
5020         
5021             // Remove any existing mouseover/mouseout listeners
5022             this._removeEventListeners();
5023         
5024             Tooltip.superclass.destroy.call(this);  
5025         
5026         },
5027         
5028         /**
5029         * Returns a string representation of the object.
5030         * @method toString
5031         * @return {String} The string representation of the Tooltip
5032         */
5033         toString: function () {
5034             return "Tooltip " + this.id;
5035         }
5036     
5037     });
5039 }());
5040 (function () {
5042     /**
5043     * Panel is an implementation of Overlay that behaves like an OS window, 
5044     * with a draggable header and an optional close icon at the top right.
5045     * @namespace YAHOO.widget
5046     * @class Panel
5047     * @extends Overlay
5048     * @constructor
5049     * @param {String} el The element ID representing the Panel <em>OR</em>
5050     * @param {HTMLElement} el The element representing the Panel
5051     * @param {Object} userConfig The configuration object literal containing 
5052     * the configuration that should be set for this Panel. See configuration 
5053     * documentation for more details.
5054     */
5055     YAHOO.widget.Panel = function (el, userConfig) {
5056     
5057         YAHOO.widget.Panel.superclass.constructor.call(this, el, userConfig);
5058     
5059     };
5062     var Lang = YAHOO.lang,
5063         DD = YAHOO.util.DD,
5064         Dom = YAHOO.util.Dom,
5065         Event = YAHOO.util.Event,
5066         Overlay = YAHOO.widget.Overlay,
5067         CustomEvent = YAHOO.util.CustomEvent,
5068         Config = YAHOO.util.Config,
5069         Panel = YAHOO.widget.Panel,
5071         m_oMaskTemplate,
5072         m_oUnderlayTemplate,
5073         m_oCloseIconTemplate,
5075         /**
5076         * Constant representing the name of the Panel's events
5077         * @property EVENT_TYPES
5078         * @private
5079         * @final
5080         * @type Object
5081         */
5082         EVENT_TYPES = {
5083         
5084             "SHOW_MASK": "showMask",
5085             "HIDE_MASK": "hideMask",
5086             "DRAG": "drag"
5087         
5088         },
5089         
5090         /**
5091         * Constant representing the Panel's configuration properties
5092         * @property DEFAULT_CONFIG
5093         * @private
5094         * @final
5095         * @type Object
5096         */
5097         DEFAULT_CONFIG = {
5098         
5099             "CLOSE": { 
5100                 key: "close", 
5101                 value: true, 
5102                 validator: Lang.isBoolean, 
5103                 supercedes: ["visible"] 
5104             },
5105             
5106             "DRAGGABLE": { 
5107                 key: "draggable", 
5108                 value: (DD ? true : false), 
5109                 validator: Lang.isBoolean, 
5110                 supercedes: ["visible"]  
5111             },
5112             
5113             "UNDERLAY": { 
5114                 key: "underlay", 
5115                 value: "shadow", 
5116                 supercedes: ["visible"] 
5117             },
5118             
5119             "MODAL": { 
5120                 key: "modal", 
5121                 value: false, 
5122                 validator: Lang.isBoolean, 
5123                 supercedes: ["visible"] 
5124             },
5125             
5126             "KEY_LISTENERS": { 
5127                 key: "keylisteners", 
5128                 suppressEvent: true, 
5129                 supercedes: ["visible"] 
5130             }
5131         
5132         };
5135     /**
5136     * Constant representing the default CSS class used for a Panel
5137     * @property YAHOO.widget.Panel.CSS_PANEL
5138     * @static
5139     * @final
5140     * @type String
5141     */
5142     Panel.CSS_PANEL = "yui-panel";
5143     
5144     /**
5145     * Constant representing the default CSS class used for a Panel's 
5146     * wrapping container
5147     * @property YAHOO.widget.Panel.CSS_PANEL_CONTAINER
5148     * @static
5149     * @final
5150     * @type String
5151     */
5152     Panel.CSS_PANEL_CONTAINER = "yui-panel-container";
5155     // Private CustomEvent listeners
5157     /* 
5158         "beforeRender" event handler that creates an empty header for a Panel 
5159         instance if its "draggable" configuration property is set to "true" 
5160         and no header has been created.
5161     */
5163     function createHeader(p_sType, p_aArgs) {
5165         if (!this.header) {
5167             this.setHeader("&#160;");
5169         }
5171     }
5174     /* 
5175         "hide" event handler that sets a Panel instance's "width"
5176         configuration property back to its original value before 
5177         "setWidthToOffsetWidth" was called.
5178     */
5179     
5180     function restoreOriginalWidth(p_sType, p_aArgs, p_oObject) {
5182         var sOriginalWidth = p_oObject[0],
5183             sNewWidth = p_oObject[1],
5184             oConfig = this.cfg,
5185             sCurrentWidth = oConfig.getProperty("width");
5187         if (sCurrentWidth == sNewWidth) {
5188             
5189             oConfig.setProperty("width", sOriginalWidth);
5190         
5191         }
5193         this.unsubscribe("hide", restoreOriginalWidth, p_oObject);
5194     
5195     }
5198     /* 
5199         "beforeShow" event handler that sets a Panel instance's "width"
5200         configuration property to the value of its root HTML 
5201         elements's offsetWidth
5202     */
5204     function setWidthToOffsetWidth(p_sType, p_aArgs) {
5206         var nIE = YAHOO.env.ua.ie,
5207             oConfig,
5208             sOriginalWidth,
5209             sNewWidth;
5211         if (nIE == 6 || (nIE == 7 && document.compatMode == "BackCompat")) {
5213             oConfig = this.cfg;
5214             sOriginalWidth = oConfig.getProperty("width");
5215             
5216             if (!sOriginalWidth || sOriginalWidth == "auto") {
5217     
5218                 sNewWidth = (this.element.offsetWidth + "px");
5219     
5220                 oConfig.setProperty("width", sNewWidth);
5221                 
5222                 this.subscribe("hide", restoreOriginalWidth, 
5223                     [(sOriginalWidth || ""), sNewWidth]);
5224             
5225             }
5226         
5227         }
5229     }
5231     /* 
5232         "focus" event handler for a focuable element.  Used to automatically 
5233         blur the element when it receives focus to ensure that a Panel 
5234         instance's modality is not compromised.
5235     */
5237     function onElementFocus() {
5239         this.blur();
5241     }
5243     /* 
5244         "showMask" event handler that adds a "focus" event handler to all
5245         focusable elements in the document to enforce a Panel instance's 
5246         modality from being compromised.
5247     */
5249     function addFocusEventHandlers(p_sType, p_aArgs) {
5251         var me = this;
5253         function isFocusable(el) {
5255             var sTagName = el.tagName.toUpperCase(),
5256                 bFocusable = false;
5257             
5258             switch (sTagName) {
5259             
5260             case "A":
5261             case "BUTTON":
5262             case "SELECT":
5263             case "TEXTAREA":
5265                 if (!Dom.isAncestor(me.element, el)) {
5266                     Event.on(el, "focus", onElementFocus, el, true);
5267                     bFocusable = true;
5268                 }
5270                 break;
5272             case "INPUT":
5274                 if (el.type != "hidden" && 
5275                     !Dom.isAncestor(me.element, el)) {
5277                     Event.on(el, "focus", onElementFocus, el, true);
5278                     bFocusable = true;
5280                 }
5282                 break;
5283             
5284             }
5286             return bFocusable;
5288         }
5290         this.focusableElements = Dom.getElementsBy(isFocusable);
5291     
5292     }
5294     /* 
5295         "hideMask" event handler that removes all "focus" event handlers added 
5296         by the "addFocusEventHandlers" method.
5297     */
5298     
5299     function removeFocusEventHandlers(p_sType, p_aArgs) {
5301         var aElements = this.focusableElements,
5302             nElements = aElements.length,
5303             el2,
5304             i;
5306         for (i = 0; i < nElements; i++) {
5307             el2 = aElements[i];
5308             Event.removeListener(el2, "focus", onElementFocus);
5309         }
5311     }
5313     
5314     YAHOO.extend(Panel, Overlay, {
5315     
5316         /**
5317         * The Overlay initialization method, which is executed for Overlay and 
5318         * all of its subclasses. This method is automatically called by the 
5319         * constructor, and  sets up all DOM references for pre-existing markup, 
5320         * and creates required markup if it is not already present.
5321         * @method init
5322         * @param {String} el The element ID representing the Overlay <em>OR</em>
5323         * @param {HTMLElement} el The element representing the Overlay
5324         * @param {Object} userConfig The configuration object literal 
5325         * containing the configuration that should be set for this Overlay. 
5326         * See configuration documentation for more details.
5327         */
5328         init: function (el, userConfig) {
5329     
5330             /*
5331                  Note that we don't pass the user config in here yet because 
5332                  we only want it executed once, at the lowest subclass level
5333             */
5335             Panel.superclass.init.call(this, el/*, userConfig*/);  
5336         
5337             this.beforeInitEvent.fire(Panel);
5338         
5339             Dom.addClass(this.element, Panel.CSS_PANEL);
5340         
5341             this.buildWrapper();
5342         
5343             if (userConfig) {
5345                 this.cfg.applyConfig(userConfig, true);
5347             }
5348         
5349             this.subscribe("showMask", addFocusEventHandlers);
5350             this.subscribe("hideMask", removeFocusEventHandlers);
5352             this.initEvent.fire(Panel);
5353             
5354         },
5355         
5356         /**
5357         * Initializes the custom events for Module which are fired 
5358         * automatically at appropriate times by the Module class.
5359         */
5360         initEvents: function () {
5361             Panel.superclass.initEvents.call(this);
5362         
5363             var SIGNATURE = CustomEvent.LIST;
5364         
5365             /**
5366             * CustomEvent fired after the modality mask is shown
5367             * @event showMaskEvent
5368             */
5369             this.showMaskEvent = this.createEvent(EVENT_TYPES.SHOW_MASK);
5370             this.showMaskEvent.signature = SIGNATURE;
5371         
5372             /**
5373             * CustomEvent fired after the modality mask is hidden
5374             * @event hideMaskEvent
5375             */
5376             this.hideMaskEvent = this.createEvent(EVENT_TYPES.HIDE_MASK);
5377             this.hideMaskEvent.signature = SIGNATURE;
5378         
5379             /**
5380             * CustomEvent when the Panel is dragged
5381             * @event dragEvent
5382             */
5383             this.dragEvent = this.createEvent(EVENT_TYPES.DRAG);
5384             this.dragEvent.signature = SIGNATURE;
5385         
5386         },
5387         
5388         /**
5389         * Initializes the class's configurable properties which can be changed 
5390         * using the Panel's Config object (cfg).
5391         * @method initDefaultConfig
5392         */
5393         initDefaultConfig: function () {
5394             Panel.superclass.initDefaultConfig.call(this);
5395         
5396             // Add panel config properties //
5397         
5398             /**
5399             * True if the Panel should display a "close" button
5400             * @config close
5401             * @type Boolean
5402             * @default true
5403             */
5404             this.cfg.addProperty(DEFAULT_CONFIG.CLOSE.key, { 
5405                 handler: this.configClose, 
5406                 value: DEFAULT_CONFIG.CLOSE.value, 
5407                 validator: DEFAULT_CONFIG.CLOSE.validator, 
5408                 supercedes: DEFAULT_CONFIG.CLOSE.supercedes 
5409             });
5410         
5411             /**
5412             * Boolean specifying if the Panel should be draggable.  The default 
5413             * value is "true" if the Drag and Drop utility is included, 
5414             * otherwise it is "false." <strong>PLEASE NOTE:</strong> There is a 
5415             * known issue in IE 6 (Strict Mode and Quirks Mode) and IE 7 
5416             * (Quirks Mode) where Panels that either don't have a value set for 
5417             * their "width" configuration property, or their "width" 
5418             * configuration property is set to "auto" will only be draggable by
5419             * placing the mouse on the text of the Panel's header element.
5420             * To fix this bug, draggable Panels missing a value for their 
5421             * "width" configuration property, or whose "width" configuration 
5422             * property is set to "auto" will have it set to the value of 
5423             * their root HTML element's offsetWidth before they are made 
5424             * visible.  The calculated width is then removed when the Panel is   
5425             * hidden. <em>This fix is only applied to draggable Panels in IE 6 
5426             * (Strict Mode and Quirks Mode) and IE 7 (Quirks Mode)</em>. For 
5427             * more information on this issue see:
5428             * SourceForge bugs #1726972 and #1589210.
5429             * @config draggable
5430             * @type Boolean
5431             * @default true
5432             */
5433             this.cfg.addProperty(DEFAULT_CONFIG.DRAGGABLE.key, { 
5434                 handler: this.configDraggable, 
5435                 value: DEFAULT_CONFIG.DRAGGABLE.value, 
5436                 validator: DEFAULT_CONFIG.DRAGGABLE.validator, 
5437                 supercedes: DEFAULT_CONFIG.DRAGGABLE.supercedes 
5438             });
5439         
5440             /**
5441             * Sets the type of underlay to display for the Panel. Valid values 
5442             * are "shadow," "matte," and "none".  <strong>PLEASE NOTE:</strong> 
5443             * The creation of the underlay element is deferred until the Panel 
5444             * is initially made visible.  For Gecko-based browsers on Mac
5445             * OS X the underlay elment is always created as it is used as a 
5446             * shim to prevent Aqua scrollbars below a Panel instance from poking 
5447             * through it (See SourceForge bug #836476).
5448             * @config underlay
5449             * @type String
5450             * @default shadow
5451             */
5452             this.cfg.addProperty(DEFAULT_CONFIG.UNDERLAY.key, { 
5453                 handler: this.configUnderlay, 
5454                 value: DEFAULT_CONFIG.UNDERLAY.value, 
5455                 supercedes: DEFAULT_CONFIG.UNDERLAY.supercedes 
5456             });
5457         
5458             /**
5459             * True if the Panel should be displayed in a modal fashion, 
5460             * automatically creating a transparent mask over the document that
5461             * will not be removed until the Panel is dismissed.
5462             * @config modal
5463             * @type Boolean
5464             * @default false
5465             */
5466             this.cfg.addProperty(DEFAULT_CONFIG.MODAL.key, { 
5467                 handler: this.configModal, 
5468                 value: DEFAULT_CONFIG.MODAL.value,
5469                 validator: DEFAULT_CONFIG.MODAL.validator, 
5470                 supercedes: DEFAULT_CONFIG.MODAL.supercedes 
5471             });
5472         
5473             /**
5474             * A KeyListener (or array of KeyListeners) that will be enabled 
5475             * when the Panel is shown, and disabled when the Panel is hidden.
5476             * @config keylisteners
5477             * @type YAHOO.util.KeyListener[]
5478             * @default null
5479             */
5480             this.cfg.addProperty(DEFAULT_CONFIG.KEY_LISTENERS.key, { 
5481                 handler: this.configKeyListeners, 
5482                 suppressEvent: DEFAULT_CONFIG.KEY_LISTENERS.suppressEvent, 
5483                 supercedes: DEFAULT_CONFIG.KEY_LISTENERS.supercedes 
5484             });
5485         
5486         },
5487         
5488         // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
5489         
5490         /**
5491         * The default event handler fired when the "close" property is changed.
5492         * The method controls the appending or hiding of the close icon at the 
5493         * top right of the Panel.
5494         * @method configClose
5495         * @param {String} type The CustomEvent type (usually the property name)
5496         * @param {Object[]} args The CustomEvent arguments. For configuration 
5497         * handlers, args[0] will equal the newly applied value for the property.
5498         * @param {Object} obj The scope object. For configuration handlers, 
5499         * this will usually equal the owner.
5500         */
5501         configClose: function (type, args, obj) {
5503             var val = args[0],
5504                 oClose = this.close;
5505         
5506             function doHide(e, obj) {
5508                 obj.hide();
5510             }
5511         
5512             if (val) {
5514                 if (!oClose) {
5516                     if (!m_oCloseIconTemplate) {
5518                         m_oCloseIconTemplate = document.createElement("span");
5519                         m_oCloseIconTemplate.innerHTML = "&#160;";
5520                         m_oCloseIconTemplate.className = "container-close";
5522                     }
5524                     oClose = m_oCloseIconTemplate.cloneNode(true);
5526                     this.innerElement.appendChild(oClose);
5528                     Event.on(oClose, "click", doHide, this);
5529                     
5530                     this.close = oClose;
5531                     
5533                 } else {
5535                     oClose.style.display = "block";
5537                 }
5539             } else {
5541                 if (oClose) {
5543                     oClose.style.display = "none";
5545                 }
5547             }
5549         },
5553         /**
5554         * The default event handler fired when the "draggable" property 
5555         * is changed.
5556         * @method configDraggable
5557         * @param {String} type The CustomEvent type (usually the property name)
5558         * @param {Object[]} args The CustomEvent arguments. For configuration 
5559         * handlers, args[0] will equal the newly applied value for the property.
5560         * @param {Object} obj The scope object. For configuration handlers, 
5561         * this will usually equal the owner.
5562         */
5563         configDraggable: function (type, args, obj) {
5564         
5565             var val = args[0];
5567             if (val) {
5568         
5569                 if (!DD) {
5570             
5571                     YAHOO.log("DD dependency not met.", "error");
5572         
5573                     this.cfg.setProperty("draggable", false);
5574             
5575                     return;
5576                 
5577                 }
5578         
5579                 if (this.header) {
5581                     Dom.setStyle(this.header, "cursor", "move");
5583                     this.registerDragDrop();
5585                 }
5587                 this.subscribe("beforeRender", createHeader);
5588                 this.subscribe("beforeShow", setWidthToOffsetWidth);
5590             } else {
5592                 if (this.dd) {
5594                     this.dd.unreg();
5596                 }
5598                 if (this.header) {
5600                     Dom.setStyle(this.header,"cursor","auto");
5602                 }
5604                 this.unsubscribe("beforeRender", createHeader);
5605                 this.unsubscribe("beforeShow", setWidthToOffsetWidth);
5607             }
5609         },
5610       
5612         /**
5613         * The default event handler fired when the "underlay" property 
5614         * is changed.
5615         * @method configUnderlay
5616         * @param {String} type The CustomEvent type (usually the property name)
5617         * @param {Object[]} args The CustomEvent arguments. For configuration 
5618         * handlers, args[0] will equal the newly applied value for the property.
5619         * @param {Object} obj The scope object. For configuration handlers, 
5620         * this will usually equal the owner.
5621         */
5622         configUnderlay: function (type, args, obj) {
5623     
5624             var UA = YAHOO.env.ua,
5625                 bMacGecko = (this.platform == "mac" && UA.gecko),
5626                 sUnderlay = args[0].toLowerCase(),
5627                 oUnderlay = this.underlay,
5628                 oElement = this.element;
5631             function createUnderlay() {
5633                 var nIE;
5635                 if (!oUnderlay) { // create if not already in DOM
5637                     if (!m_oUnderlayTemplate) {
5639                         m_oUnderlayTemplate = document.createElement("div");
5640                         m_oUnderlayTemplate.className = "underlay";
5641                     
5642                     }
5644                     oUnderlay = m_oUnderlayTemplate.cloneNode(false);
5645                     this.element.appendChild(oUnderlay);
5646                     
5647                     this.underlay = oUnderlay;
5649                     nIE = UA.ie;
5651                     if (nIE == 6 || 
5652                         (nIE == 7 && document.compatMode == "BackCompat")) {
5653                             
5654                         this.sizeUnderlay();
5656                         this.cfg.subscribeToConfigEvent("width", 
5657                             this.sizeUnderlay);
5659                         this.cfg.subscribeToConfigEvent("height", 
5660                             this.sizeUnderlay);
5662                         this.changeContentEvent.subscribe(this.sizeUnderlay);
5664                         YAHOO.widget.Module.textResizeEvent.subscribe(
5665                             this.sizeUnderlay, this, true);
5666                     
5667                     }
5669                 }
5671             }
5674             function onBeforeShow() {
5675             
5676                 createUnderlay.call(this);
5677     
5678                 this._underlayDeferred = false;
5679     
5680                 this.beforeShowEvent.unsubscribe(onBeforeShow);
5681             
5682             }
5684             
5685             function destroyUnderlay() {
5687                 if (this._underlayDeferred) {
5689                     this.beforeShowEvent.unsubscribe(onBeforeShow);
5690                 
5691                     this._underlayDeferred = false;
5693                 }
5694             
5695                 if (oUnderlay) {
5696             
5697                     this.cfg.unsubscribeFromConfigEvent("width", 
5698                         this.sizeUnderlay);
5699     
5700                     this.cfg.unsubscribeFromConfigEvent("height", 
5701                         this.sizeUnderlay);
5702     
5703                     this.changeContentEvent.unsubscribe(this.sizeUnderlay);
5704     
5705                     YAHOO.widget.Module.textResizeEvent.unsubscribe(
5706                         this.sizeUnderlay, this, true);
5707     
5708                     this.element.removeChild(oUnderlay);
5709                     
5710                     this.underlay = null;
5712                 }
5713                     
5714             }
5715         
5717             switch (sUnderlay) {
5718     
5719             case "shadow":
5721                 Dom.removeClass(oElement, "matte");
5722                 Dom.addClass(oElement, "shadow");
5724                 break;
5726             case "matte":
5728                 if (!bMacGecko) {
5730                     destroyUnderlay.call(this);
5732                 }
5733             
5734                 Dom.removeClass(oElement, "shadow");
5735                 Dom.addClass(oElement, "matte");
5737                 break;
5739             default:
5741                 if (!bMacGecko) {
5743                     destroyUnderlay.call(this);
5745                 }
5746             
5747                 Dom.removeClass(oElement, "shadow");
5748                 Dom.removeClass(oElement, "matte");
5750                 break;
5752             }
5755             if ((sUnderlay == "shadow") || (bMacGecko && !oUnderlay)) {
5756                 
5757                 if (this.cfg.getProperty("visible")) {
5758                 
5759                     createUnderlay.call(this);
5760                 
5761                 }
5762                 else {
5764                     if (!this._underlayDeferred) {
5766                         this.beforeShowEvent.subscribe(onBeforeShow);
5767                     
5768                         this._underlayDeferred = true;
5770                     }
5771                 
5772                 }
5774             }
5775     
5776         },
5777         
5778         /**
5779         * The default event handler fired when the "modal" property is 
5780         * changed. This handler subscribes or unsubscribes to the show and hide
5781         * events to handle the display or hide of the modality mask.
5782         * @method configModal
5783         * @param {String} type The CustomEvent type (usually the property name)
5784         * @param {Object[]} args The CustomEvent arguments. For configuration 
5785         * handlers, args[0] will equal the newly applied value for the property.
5786         * @param {Object} obj The scope object. For configuration handlers, 
5787         * this will usually equal the owner.
5788         */
5789         configModal: function (type, args, obj) {
5791             var modal = args[0];
5793             if (modal) {
5795                 if (!this._hasModalityEventListeners) {
5797                     this.subscribe("beforeShow", this.buildMask);
5798                     this.subscribe("beforeShow", this.bringToTop);
5799                     this.subscribe("beforeShow", this.showMask);
5800                     this.subscribe("hide", this.hideMask);
5802                     Overlay.windowResizeEvent.subscribe(this.sizeMask, 
5803                         this, true);
5805                     this._hasModalityEventListeners = true;
5807                 }
5809             } else {
5811                 if (this._hasModalityEventListeners) {
5813                     if (this.cfg.getProperty("visible")) {
5814                     
5815                         this.hideMask();
5816                         this.removeMask();
5817                     
5818                     }
5820                     this.unsubscribe("beforeShow", this.buildMask);
5821                     this.unsubscribe("beforeShow", this.bringToTop);
5822                     this.unsubscribe("beforeShow", this.showMask);
5823                     this.unsubscribe("hide", this.hideMask);
5825                     Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
5826                     
5827                     this._hasModalityEventListeners = false;
5828                 
5829                 }
5831             }
5833         },
5834         
5835         /**
5836         * Removes the modality mask.
5837         * @method removeMask
5838         */
5839         removeMask: function () {
5840         
5841             var oMask = this.mask,
5842                 oParentNode;
5843         
5844             if (oMask) {
5845             
5846                 /*
5847                     Hide the mask before destroying it to ensure that DOM
5848                     event handlers on focusable elements get removed.
5849                 */
5850         
5851                 this.hideMask();
5852             
5853                 oParentNode = oMask.parentNode;
5854         
5855                 if (oParentNode) {
5856         
5857                     oParentNode.removeChild(oMask);
5858         
5859                 }
5860         
5861                 this.mask = null;
5862             }
5863             
5864         },
5865         
5866         /**
5867         * The default event handler fired when the "keylisteners" property 
5868         * is changed.
5869         * @method configKeyListeners
5870         * @param {String} type The CustomEvent type (usually the property name)
5871         * @param {Object[]} args The CustomEvent arguments. For configuration
5872         * handlers, args[0] will equal the newly applied value for the property.
5873         * @param {Object} obj The scope object. For configuration handlers, 
5874         * this will usually equal the owner.
5875         */
5876         configKeyListeners: function (type, args, obj) {
5878             var listeners = args[0],
5879                 listener,
5880                 nListeners,
5881                 i;
5882         
5883             if (listeners) {
5885                 if (listeners instanceof Array) {
5887                     nListeners = listeners.length;
5889                     for (i = 0; i < nListeners; i++) {
5891                         listener = listeners[i];
5892         
5893                         if (!Config.alreadySubscribed(this.showEvent, 
5894                             listener.enable, listener)) {
5896                             this.showEvent.subscribe(listener.enable, 
5897                                 listener, true);
5899                         }
5901                         if (!Config.alreadySubscribed(this.hideEvent, 
5902                             listener.disable, listener)) {
5904                             this.hideEvent.subscribe(listener.disable, 
5905                                 listener, true);
5907                             this.destroyEvent.subscribe(listener.disable, 
5908                                 listener, true);
5909                         }
5911                     }
5913                 } else {
5915                     if (!Config.alreadySubscribed(this.showEvent, 
5916                         listeners.enable, listeners)) {
5918                         this.showEvent.subscribe(listeners.enable, 
5919                             listeners, true);
5920                     }
5922                     if (!Config.alreadySubscribed(this.hideEvent, 
5923                         listeners.disable, listeners)) {
5925                         this.hideEvent.subscribe(listeners.disable, 
5926                             listeners, true);
5928                         this.destroyEvent.subscribe(listeners.disable, 
5929                             listeners, true);
5931                     }
5933                 }
5935             }
5937         },
5938         
5939         /**
5940         * The default event handler fired when the "height" property is changed.
5941         * @method configHeight
5942         * @param {String} type The CustomEvent type (usually the property name)
5943         * @param {Object[]} args The CustomEvent arguments. For configuration 
5944         * handlers, args[0] will equal the newly applied value for the property.
5945         * @param {Object} obj The scope object. For configuration handlers, 
5946         * this will usually equal the owner.
5947         */
5948         configHeight: function (type, args, obj) {
5949     
5950             var height = args[0],
5951                 el = this.innerElement;
5952     
5953             Dom.setStyle(el, "height", height);
5954             this.cfg.refireEvent("iframe");
5955     
5956         },
5957         
5958         /**
5959         * The default event handler fired when the "width" property is changed.
5960         * @method configWidth
5961         * @param {String} type The CustomEvent type (usually the property name)
5962         * @param {Object[]} args The CustomEvent arguments. For configuration 
5963         * handlers, args[0] will equal the newly applied value for the property.
5964         * @param {Object} obj The scope object. For configuration handlers, 
5965         * this will usually equal the owner.
5966         */
5967         configWidth: function (type, args, obj) {
5968     
5969             var width = args[0],
5970                 el = this.innerElement;
5971     
5972             Dom.setStyle(el, "width", width);
5973             this.cfg.refireEvent("iframe");
5974     
5975         },
5976         
5977         /**
5978         * The default event handler fired when the "zIndex" property is changed.
5979         * @method configzIndex
5980         * @param {String} type The CustomEvent type (usually the property name)
5981         * @param {Object[]} args The CustomEvent arguments. For configuration 
5982         * handlers, args[0] will equal the newly applied value for the property.
5983         * @param {Object} obj The scope object. For configuration handlers, 
5984         * this will usually equal the owner.
5985         */
5986         configzIndex: function (type, args, obj) {
5987     
5988             Panel.superclass.configzIndex.call(this, type, args, obj);
5989         
5990             var maskZ = 0,
5991                 currentZ = Dom.getStyle(this.element, "zIndex");
5992         
5993             if (this.mask) {
5995                 if (!currentZ || isNaN(currentZ)) {
5996                     currentZ = 0;
5997                 }
5998         
5999                 if (currentZ === 0) {
6001                     this.cfg.setProperty("zIndex", 1);
6003                 } else {
6005                     maskZ = currentZ - 1;
6006                     Dom.setStyle(this.mask, "zIndex", maskZ);
6008                 }
6009         
6010             }
6011         },
6012         
6013         // END BUILT-IN PROPERTY EVENT HANDLERS //
6014         
6015         
6016         /**
6017         * Builds the wrapping container around the Panel that is used for 
6018         * positioning the shadow and matte underlays. The container element is 
6019         * assigned to a  local instance variable called container, and the 
6020         * element is reinserted inside of it.
6021         * @method buildWrapper
6022         */
6023         buildWrapper: function () {
6024     
6025             var elementParent = this.element.parentNode,
6026                 originalElement = this.element,
6027                 wrapper = document.createElement("div");
6028     
6029             wrapper.className = Panel.CSS_PANEL_CONTAINER;
6030             wrapper.id = originalElement.id + "_c";
6031         
6032             if (elementParent) {
6033                 elementParent.insertBefore(wrapper, originalElement);
6034             }
6035         
6036             wrapper.appendChild(originalElement);
6037         
6038             this.element = wrapper;
6039             this.innerElement = originalElement;
6040         
6041             Dom.setStyle(this.innerElement, "visibility", "inherit");
6042         },
6043         
6044         /**
6045         * Adjusts the size of the shadow based on the size of the element.
6046         * @method sizeUnderlay
6047         */
6048         sizeUnderlay: function () {
6050             var oUnderlay = this.underlay,
6051                 oElement;
6053             if (oUnderlay) {
6055                 oElement = this.element;
6057                 oUnderlay.style.width = oElement.offsetWidth + "px";
6058                 oUnderlay.style.height = oElement.offsetHeight + "px";
6060             }
6062         },
6064         
6065         /**
6066         * Registers the Panel's header for drag & drop capability.
6067         * @method registerDragDrop
6068         */
6069         registerDragDrop: function () {
6070     
6071             var me = this;
6072     
6073             if (this.header) {
6074         
6075                 if (!DD) {
6076         
6077                     YAHOO.log("DD dependency not met.", "error");
6078         
6079                     return;
6080                 
6081                 }
6082         
6083                 this.dd = new DD(this.element.id, this.id);
6084         
6085                 if (!this.header.id) {
6086                     this.header.id = this.id + "_h";
6087                 }
6088         
6089     
6090                 this.dd.startDrag = function () {
6091         
6092                     var offsetHeight,
6093                         offsetWidth,
6094                         viewPortWidth,
6095                         viewPortHeight,
6096                         scrollX,
6097                         scrollY,
6098                         topConstraint,
6099                         leftConstraint,
6100                         bottomConstraint,
6101                         rightConstraint;
6102     
6103                     if (YAHOO.env.ua.ie == 6) {
6104                         Dom.addClass(me.element,"drag");
6105                     }
6106         
6107                     if (me.cfg.getProperty("constraintoviewport")) {
6108     
6109                         offsetHeight = me.element.offsetHeight;
6110                         offsetWidth = me.element.offsetWidth;
6111                         
6112                         viewPortWidth = Dom.getViewportWidth();
6113                         viewPortHeight = Dom.getViewportHeight();
6114                         
6115                         scrollX = Dom.getDocumentScrollLeft();
6116                         scrollY = Dom.getDocumentScrollTop();
6117                         
6118                         topConstraint = scrollY + 10;
6119                         leftConstraint = scrollX + 10;
6121                         bottomConstraint = 
6122                             scrollY + viewPortHeight - offsetHeight - 10;
6124                         rightConstraint = 
6125                             scrollX + viewPortWidth - offsetWidth - 10;
6126         
6127                         this.minX = leftConstraint;
6128                         this.maxX = rightConstraint;
6129                         this.constrainX = true;
6130         
6131                         this.minY = topConstraint;
6132                         this.maxY = bottomConstraint;
6133                         this.constrainY = true;
6134     
6135                     } else {
6136     
6137                         this.constrainX = false;
6138                         this.constrainY = false;
6139     
6140                     }
6141         
6142                     me.dragEvent.fire("startDrag", arguments);
6143                 };
6144         
6145                 this.dd.onDrag = function () {
6146                     me.syncPosition();
6147                     me.cfg.refireEvent("iframe");
6148                     if (this.platform == "mac" && YAHOO.env.ua.gecko) {
6149                         this.showMacGeckoScrollbars();
6150                     }
6151         
6152                     me.dragEvent.fire("onDrag", arguments);
6153                 };
6154         
6155                 this.dd.endDrag = function () {
6157                     if (YAHOO.env.ua.ie == 6) {
6158                         Dom.removeClass(me.element,"drag");
6159                     }
6160         
6161                     me.dragEvent.fire("endDrag", arguments);
6162                     me.moveEvent.fire(me.cfg.getProperty("xy"));
6163                     
6164                 };
6165         
6166                 this.dd.setHandleElId(this.header.id);
6167                 this.dd.addInvalidHandleType("INPUT");
6168                 this.dd.addInvalidHandleType("SELECT");
6169                 this.dd.addInvalidHandleType("TEXTAREA");
6170             }
6171         },
6172         
6173         /**
6174         * Builds the mask that is laid over the document when the Panel is 
6175         * configured to be modal.
6176         * @method buildMask
6177         */
6178         buildMask: function () {
6179     
6180             var oMask = this.mask;
6181     
6182             if (!oMask) {
6184                 if (!m_oMaskTemplate) {
6185                 
6186                     m_oMaskTemplate = document.createElement("div");
6187                     m_oMaskTemplate.className = "mask";
6188                     m_oMaskTemplate.innerHTML = "&#160;";
6189                 
6190                 }
6192                 oMask = m_oMaskTemplate.cloneNode(true);
6193                 oMask.id = this.id + "_mask";
6195                 document.body.insertBefore(oMask, document.body.firstChild);
6196                 
6197                 this.mask = oMask;
6199             }
6201         },
6202         
6203         /**
6204         * Hides the modality mask.
6205         * @method hideMask
6206         */
6207         hideMask: function () {
6208             if (this.cfg.getProperty("modal") && this.mask) {
6209                 this.mask.style.display = "none";
6210                 this.hideMaskEvent.fire();
6211                 Dom.removeClass(document.body, "masked");
6212             }
6213         },
6214         
6215         /**
6216         * Shows the modality mask.
6217         * @method showMask
6218         */
6219         showMask: function () {
6220             if (this.cfg.getProperty("modal") && this.mask) {
6221                 Dom.addClass(document.body, "masked");
6222                 this.sizeMask();
6223                 this.mask.style.display = "block";
6224                 this.showMaskEvent.fire();
6225             }
6226         },
6227         
6228         /**
6229         * Sets the size of the modality mask to cover the entire scrollable 
6230         * area of the document
6231         * @method sizeMask
6232         */
6233         sizeMask: function () {
6235             if (this.mask) {
6237                 this.mask.style.height = Dom.getDocumentHeight() + "px";
6238                 this.mask.style.width = Dom.getDocumentWidth() + "px";
6240             }
6242         },
6244         
6245         /**
6246         * Renders the Panel by inserting the elements that are not already in 
6247         * the main Panel into their correct places. Optionally appends the 
6248         * Panel to the specified node prior to the render's execution. NOTE: 
6249         * For Panels without existing markup, the appendToNode argument is 
6250         * REQUIRED. If this argument is ommitted and the current element is 
6251         * not present in the document, the function will return false, 
6252         * indicating that the render was a failure.
6253         * @method render
6254         * @param {String} appendToNode The element id to which the Module 
6255         * should be appended to prior to rendering <em>OR</em>
6256         * @param {HTMLElement} appendToNode The element to which the Module 
6257         * should be appended to prior to rendering
6258         * @return {boolean} Success or failure of the render
6259         */
6260         render: function (appendToNode) {
6262             return Panel.superclass.render.call(this, 
6263                 appendToNode, this.innerElement);
6265         },
6266         
6267         /**
6268         * Removes the Panel element from the DOM and sets all child elements
6269         * to null.
6270         * @method destroy
6271         */
6272         destroy: function () {
6273         
6274             Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
6275             
6276             this.removeMask();
6277         
6278             if (this.close) {
6279             
6280                 Event.purgeElement(this.close);
6281         
6282             }
6283         
6284             Panel.superclass.destroy.call(this);  
6285         
6286         },
6287         
6288         /**
6289         * Returns a String representation of the object.
6290         * @method toString
6291         * @return {String} The string representation of the Panel.
6292         */
6293         toString: function () {
6294             return "Panel " + this.id;
6295         }
6296     
6297     });
6299 }());
6300 (function () {
6302     /**
6303     * Dialog is an implementation of Panel that can be used to submit form 
6304     * data. Built-in functionality for buttons with event handlers is included, 
6305     * and button sets can be build dynamically, or the preincluded ones for 
6306     * Submit/Cancel and OK/Cancel can be utilized. Forms can be processed in 3
6307     * ways -- via an asynchronous Connection utility call, a simple form 
6308     * POST or GET, or manually.
6309     * @namespace YAHOO.widget
6310     * @class Dialog
6311     * @extends YAHOO.widget.Panel
6312     * @constructor
6313     * @param {String} el The element ID representing the Dialog <em>OR</em>
6314     * @param {HTMLElement} el The element representing the Dialog
6315     * @param {Object} userConfig The configuration object literal containing 
6316     * the configuration that should be set for this Dialog. See configuration 
6317     * documentation for more details.
6318     */
6319     YAHOO.widget.Dialog = function (el, userConfig) {
6320     
6321         YAHOO.widget.Dialog.superclass.constructor.call(this, el, userConfig);
6322     
6323     };
6326     var Event = YAHOO.util.Event,
6327         CustomEvent = YAHOO.util.CustomEvent,
6328         Dom = YAHOO.util.Dom,
6329         KeyListener = YAHOO.util.KeyListener,
6330         Connect = YAHOO.util.Connect,
6331         Dialog = YAHOO.widget.Dialog,
6332         Lang = YAHOO.lang,
6334         /**
6335         * Constant representing the name of the Dialog's events
6336         * @property EVENT_TYPES
6337         * @private
6338         * @final
6339         * @type Object
6340         */
6341         EVENT_TYPES = {
6342         
6343             "BEFORE_SUBMIT": "beforeSubmit",
6344             "SUBMIT": "submit",
6345             "MANUAL_SUBMIT": "manualSubmit",
6346             "ASYNC_SUBMIT": "asyncSubmit",
6347             "FORM_SUBMIT": "formSubmit",
6348             "CANCEL": "cancel"
6349         
6350         },
6351         
6352         /**
6353         * Constant representing the Dialog's configuration properties
6354         * @property DEFAULT_CONFIG
6355         * @private
6356         * @final
6357         * @type Object
6358         */
6359         DEFAULT_CONFIG = {
6360         
6361             "POST_METHOD": { 
6362                 key: "postmethod", 
6363                 value: "async" 
6364             },
6365             
6366             "BUTTONS": { 
6367                 key: "buttons", 
6368                 value: "none" 
6369             }
6370         
6371         };    
6374     /**
6375     * Constant representing the default CSS class used for a Dialog
6376     * @property YAHOO.widget.Dialog.CSS_DIALOG
6377     * @static
6378     * @final
6379     * @type String
6380     */
6381     Dialog.CSS_DIALOG = "yui-dialog";
6384     function removeButtonEventHandlers() {
6386         var aButtons = this._aButtons,
6387             nButtons,
6388             oButton,
6389             i;
6391         if (Lang.isArray(aButtons)) {
6393             nButtons = aButtons.length;
6395             if (nButtons > 0) {
6397                 i = nButtons - 1;
6399                 do {
6401                     oButton = aButtons[i];
6402                     
6403                     if (oButton instanceof YAHOO.widget.Button) {
6404                         
6405                         oButton.destroy();
6406                         
6407                     }
6408                     else if (oButton.tagName.toUpperCase() == "BUTTON") {
6410                         Event.purgeElement(oButton);
6411                         Event.purgeElement(oButton, false);
6413                     }
6415                 }
6416                 while (i--);
6417             
6418             }
6419         
6420         }
6422     }
6423     
6424     
6425     YAHOO.extend(Dialog, YAHOO.widget.Panel, { 
6427         
6428         /**
6429         * @property form
6430         * @description Object reference to the Dialog's 
6431         * <code>&#60;form&#62;</code> element.
6432         * @default null 
6433         * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6434         * level-one-html.html#ID-40002357">HTMLFormElement</a>
6435         */
6436         form: null,
6437     
6438         /**
6439         * Initializes the class's configurable properties which can be changed 
6440         * using the Dialog's Config object (cfg).
6441         * @method initDefaultConfig
6442         */
6443         initDefaultConfig: function () {
6444             Dialog.superclass.initDefaultConfig.call(this);
6445         
6446             /**
6447             * The internally maintained callback object for use with the 
6448             * Connection utility
6449             * @property callback
6450             * @type Object
6451             */
6452             this.callback = {
6453     
6454                 /**
6455                 * The function to execute upon success of the 
6456                 * Connection submission
6457                 * @property callback.success
6458                 * @type Function
6459                 */
6460                 success: null,
6461     
6462                 /**
6463                 * The function to execute upon failure of the 
6464                 * Connection submission
6465                 * @property callback.failure
6466                 * @type Function
6467                 */
6468                 failure: null,
6469     
6470                 /**
6471                 * The arbitraty argument or arguments to pass to the Connection 
6472                 * callback functions
6473                 * @property callback.argument
6474                 * @type Object
6475                 */
6476                 argument: null
6477     
6478             };
6479         
6481             // Add form dialog config properties //
6482             
6483             /**
6484             * The method to use for posting the Dialog's form. Possible values 
6485             * are "async", "form", and "manual".
6486             * @config postmethod
6487             * @type String
6488             * @default async
6489             */
6490             this.cfg.addProperty(DEFAULT_CONFIG.POST_METHOD.key, {
6491                 handler: this.configPostMethod, 
6492                 value: DEFAULT_CONFIG.POST_METHOD.value, 
6493                 validator: function (val) {
6494                     if (val != "form" && val != "async" && val != "none" && 
6495                         val != "manual") {
6496                         return false;
6497                     } else {
6498                         return true;
6499                     }
6500                 }
6501             });
6502             
6503             /**
6504             * Array of object literals, each containing a set of properties 
6505             * defining a button to be appended into the Dialog's footer.
6506             * Each button object in the buttons array can have three properties:
6507             * <dt>text:</dt>
6508             * <dd>The text that will display on the face of the button.  <em>
6509             * Please note:</em> As of version 2.3, the text can include 
6510             * HTML.</dd>
6511             * <dt>handler:</dt>
6512             * <dd>Can be either:
6513             *     <ol>
6514             *         <li>A reference to a function that should fire when the 
6515             * button is clicked.  (In this case scope of this function is 
6516             * always its Dialog instance.)</li>
6517             *         <li>An object literal representing the code to be 
6518             * executed when the button is clicked.  Format:<br> <code> {<br>  
6519             * <strong>fn:</strong> Function,   &#47;&#47; The handler to call 
6520             * when  the event fires.<br> <strong>obj:</strong> Object, 
6521             * &#47;&#47; An  object to pass back to the handler.<br> <strong>
6522             * scope:</strong>  Object &#47;&#47; The object to use for the 
6523             * scope of the handler. <br> } </code> <br><em>Please note: this 
6524             * functionality was added in version 2.3.</em></li>
6525             *     </ol>
6526             * </dd>
6527             * <dt>isDefault:</dt>
6528             * <dd>An optional boolean value that specifies that a button 
6529             * should be highlighted and focused by default.</dd>
6530             * @config buttons
6531             * @type {Array|String}
6532             * @default "none"
6533             */
6534             this.cfg.addProperty(DEFAULT_CONFIG.BUTTONS.key, {
6535                 handler: this.configButtons,
6536                 value: DEFAULT_CONFIG.BUTTONS.value
6537             }); 
6538             
6539         },
6540         
6541         /**
6542         * Initializes the custom events for Dialog which are fired 
6543         * automatically at appropriate times by the Dialog class.
6544         * @method initEvents
6545         */
6546         initEvents: function () {
6547             Dialog.superclass.initEvents.call(this);
6548         
6549             var SIGNATURE = CustomEvent.LIST;
6550         
6551             /**
6552             * CustomEvent fired prior to submission
6553             * @event beforeSubmitEvent
6554             */ 
6555             this.beforeSubmitEvent = 
6556                 this.createEvent(EVENT_TYPES.BEFORE_SUBMIT);
6557             this.beforeSubmitEvent.signature = SIGNATURE;
6558             
6559             /**
6560             * CustomEvent fired after submission
6561             * @event submitEvent
6562             */
6563             this.submitEvent = this.createEvent(EVENT_TYPES.SUBMIT);
6564             this.submitEvent.signature = SIGNATURE;
6565         
6566             /**
6567             * CustomEvent fired prior to manual submission
6568             * @event manualSubmitEvent
6569             */
6570             this.manualSubmitEvent = 
6571                 this.createEvent(EVENT_TYPES.MANUAL_SUBMIT);
6572             this.manualSubmitEvent.signature = SIGNATURE;
6573         
6574             /**
6575             * CustomEvent fired prior to asynchronous submission
6576             * @event asyncSubmitEvent
6577             */ 
6578             this.asyncSubmitEvent = this.createEvent(EVENT_TYPES.ASYNC_SUBMIT);
6579             this.asyncSubmitEvent.signature = SIGNATURE;
6580         
6581             /**
6582             * CustomEvent fired prior to form-based submission
6583             * @event formSubmitEvent
6584             */
6585             this.formSubmitEvent = this.createEvent(EVENT_TYPES.FORM_SUBMIT);
6586             this.formSubmitEvent.signature = SIGNATURE;
6587         
6588             /**
6589             * CustomEvent fired after cancel
6590             * @event cancelEvent
6591             */
6592             this.cancelEvent = this.createEvent(EVENT_TYPES.CANCEL);
6593             this.cancelEvent.signature = SIGNATURE;
6594         
6595         },
6596         
6597         /**
6598         * The Dialog initialization method, which is executed for Dialog and 
6599         * all of its subclasses. This method is automatically called by the 
6600         * constructor, and  sets up all DOM references for pre-existing markup, 
6601         * and creates required markup if it is not already present.
6602         * @method init
6603         * @param {String} el The element ID representing the Dialog <em>OR</em>
6604         * @param {HTMLElement} el The element representing the Dialog
6605         * @param {Object} userConfig The configuration object literal 
6606         * containing the configuration that should be set for this Dialog. 
6607         * See configuration documentation for more details.
6608         */
6609         init: function (el, userConfig) {
6611             /*
6612                  Note that we don't pass the user config in here yet because 
6613                  we only want it executed once, at the lowest subclass level
6614             */
6616             Dialog.superclass.init.call(this, el/*, userConfig*/); 
6617         
6618             this.beforeInitEvent.fire(Dialog);
6619         
6620             Dom.addClass(this.element, Dialog.CSS_DIALOG);
6621         
6622             this.cfg.setProperty("visible", false);
6623         
6624             if (userConfig) {
6625                 this.cfg.applyConfig(userConfig, true);
6626             }
6627         
6628             this.showEvent.subscribe(this.focusFirst, this, true);
6629             this.beforeHideEvent.subscribe(this.blurButtons, this, true);
6631             this.subscribe("changeBody", this.registerForm);
6632         
6633             this.initEvent.fire(Dialog);
6634         },
6635         
6636         /**
6637         * Submits the Dialog's form depending on the value of the 
6638         * "postmethod" configuration property.  <strong>Please note:
6639         * </strong> As of version 2.3 this method will automatically handle 
6640         * asyncronous file uploads should the Dialog instance's form contain 
6641         * <code>&#60;input type="file"&#62;</code> elements.  If a Dialog 
6642         * instance will be handling asyncronous file uploads, its 
6643         * <code>callback</code> property will need to be setup with a 
6644         * <code>upload</code> handler rather than the standard 
6645         * <code>success</code> and, or <code>failure</code> handlers.  For more 
6646         * information, see the <a href="http://developer.yahoo.com/yui/
6647         * connection/#file">Connection Manager documenation on file uploads</a>.
6648         * @method doSubmit
6649         */
6650         doSubmit: function () {
6651     
6652             var oForm = this.form,
6653                 bUseFileUpload = false,
6654                 bUseSecureFileUpload = false,
6655                 aElements,
6656                 nElements,
6657                 i,
6658                 sMethod;
6661             switch (this.cfg.getProperty("postmethod")) {
6662     
6663             case "async":
6665                 aElements = oForm.elements;
6666                 nElements = aElements.length;
6668                 if (nElements > 0) {
6669                 
6670                     i = nElements - 1;
6671                 
6672                     do {
6673                     
6674                         if (aElements[i].type == "file") {
6675                         
6676                             bUseFileUpload = true;
6677                             break;
6678                         
6679                         }
6680                     
6681                     }
6682                     while(i--);
6683                 
6684                 }
6686                 if (bUseFileUpload && YAHOO.env.ua.ie && this.isSecure) {
6688                     bUseSecureFileUpload = true;
6689                 
6690                 }
6692                 sMethod = 
6693                     (oForm.getAttribute("method") || "POST").toUpperCase();
6695                 Connect.setForm(oForm, bUseFileUpload, bUseSecureFileUpload);
6697                 Connect.asyncRequest(sMethod, oForm.getAttribute("action"), 
6698                     this.callback);
6700                 this.asyncSubmitEvent.fire();
6702                 break;
6704             case "form":
6706                 oForm.submit();
6707                 this.formSubmitEvent.fire();
6709                 break;
6711             case "none":
6712             case "manual":
6714                 this.manualSubmitEvent.fire();
6716                 break;
6717     
6718             }
6719     
6720         },
6721         
6722         
6723         /**
6724         * Prepares the Dialog's internal FORM object, creating one if one is
6725         * not currently present.
6726         * @method registerForm
6727         */
6728         registerForm: function () {
6729     
6730             var form = this.element.getElementsByTagName("form")[0],
6731                 me = this,
6732                 firstElement,
6733                 lastElement;
6736             if (this.form) {
6738                 if (this.form == form && 
6739                     Dom.isAncestor(this.element, this.form)) {
6740     
6741                     return;
6742     
6743                 }
6744                 else {
6746                     Event.purgeElement(this.form);
6747                     
6748                     this.form = null;                
6749                 
6750                 }
6751             
6752             }
6753         
6755             if (!form) {
6757                 form = document.createElement("form");
6758                 form.name = "frm_" + this.id;
6760                 this.body.appendChild(form);
6762             }
6765             if (form) {
6767                 this.form = form;
6769                 Event.on(form, "submit", function (e) {
6771                     Event.stopEvent(e);
6773                     this.submit();
6774                     this.form.blur();
6775         
6776                 });
6779                 this.firstFormElement = function () {
6780         
6781                     var f, el, nElements = form.elements.length;
6782         
6783                     for (f = 0; f < nElements; f++) {
6784     
6785                         el = form.elements[f];
6786     
6787                         if (el.focus && !el.disabled && el.type != "hidden") {
6788     
6789                             return el;
6790     
6791                         }
6792     
6793                     }
6794     
6795                     return null;
6796                     
6797                 }();
6798             
6799                 this.lastFormElement = function () {
6800         
6801                     var f, el, nElements = form.elements.length;
6802         
6803                     for (f = nElements - 1; f >= 0; f--) {
6804     
6805                         el = form.elements[f];
6806     
6807                         if (el.focus && !el.disabled && el.type != "hidden") {
6808     
6809                             return el;
6810     
6811                         }
6812     
6813                     }
6814     
6815                     return null;
6816     
6817                 }();
6818             
6819                 if (this.cfg.getProperty("modal")) {
6820             
6821                     firstElement = this.firstFormElement || this.firstButton;
6822         
6823                     if (firstElement) {
6824     
6825                         this.preventBackTab = new KeyListener(firstElement, 
6826                             { shift: true, keys: 9 }, 
6827                             { fn: me.focusLast, scope: me, 
6828                             correctScope: true });
6829     
6830                         this.showEvent.subscribe(this.preventBackTab.enable, 
6831                             this.preventBackTab, true);
6832     
6833                         this.hideEvent.subscribe(this.preventBackTab.disable, 
6834                             this.preventBackTab, true);
6835                     }
6836             
6837                     lastElement = this.lastButton || this.lastFormElement;
6838     
6839                     if (lastElement) {
6840     
6841                         this.preventTabOut = new KeyListener(lastElement, 
6842                             { shift: false, keys: 9 }, 
6843                             { fn: me.focusFirst, scope: me, 
6844                             correctScope: true });
6845     
6846                         this.showEvent.subscribe(this.preventTabOut.enable, 
6847                             this.preventTabOut, true);
6848     
6849                         this.hideEvent.subscribe(this.preventTabOut.disable, 
6850                             this.preventTabOut, true);
6851     
6852                     }
6853                 }
6854             
6855             }
6857         },
6858         
6859         // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
6860         
6861         /**
6862         * The default event handler fired when the "close" property is 
6863         * changed. The method controls the appending or hiding of the close
6864         * icon at the top right of the Dialog.
6865         * @method configClose
6866         * @param {String} type The CustomEvent type (usually the property name)
6867         * @param {Object[]} args The CustomEvent arguments. For 
6868         * configuration handlers, args[0] will equal the newly applied value 
6869         * for the property.
6870         * @param {Object} obj The scope object. For configuration handlers, 
6871         * this will usually equal the owner.
6872         */
6873         configClose: function (type, args, obj) {
6874             var val = args[0];
6875         
6876             function doCancel(e, obj) {
6877                 obj.cancel();
6878             }
6879         
6880             if (val) {
6881                 if (! this.close) {
6882                     this.close = document.createElement("div");
6883                     Dom.addClass(this.close, "container-close");
6884         
6885                     this.close.innerHTML = "&#160;";
6886                     this.innerElement.appendChild(this.close);
6887                     Event.on(this.close, "click", doCancel, this);
6888                 } else {
6889                     this.close.style.display = "block";
6890                 }
6891             } else {
6892                 if (this.close) {
6893                     this.close.style.display = "none";
6894                 }
6895             }
6896         },
6897         
6898         /**
6899         * The default event handler for the "buttons" configuration property
6900         * @method configButtons
6901         * @param {String} type The CustomEvent type (usually the property name)
6902         * @param {Object[]} args The CustomEvent arguments. For configuration 
6903         * handlers, args[0] will equal the newly applied value for the property.
6904         * @param {Object} obj The scope object. For configuration handlers, 
6905         * this will usually equal the owner.
6906         */
6907         configButtons: function (type, args, obj) {
6908     
6909             var Button = YAHOO.widget.Button,
6910                 aButtons = args[0],
6911                 oInnerElement = this.innerElement,
6912                 oButton,
6913                 oButtonEl,
6914                 oYUIButton,
6915                 nButtons,
6916                 oSpan,
6917                 oFooter,
6918                 i;
6920             removeButtonEventHandlers.call(this);
6921             
6922             this._aButtons = null;
6924             if (Lang.isArray(aButtons)) {
6926                 oSpan = document.createElement("span");
6927                 oSpan.className = "button-group";
6929                 nButtons = aButtons.length;
6931                 this._aButtons = [];
6932         
6933                 for (i = 0; i < nButtons; i++) {
6935                     oButton = aButtons[i];
6937                     if (Button) {
6939                         oYUIButton = new Button({ label: oButton.text, 
6940                                             container: oSpan });
6942                         oButtonEl = oYUIButton.get("element");
6944                         if (oButton.isDefault) {
6946                             oYUIButton.addClass("default");
6948                             this.defaultHtmlButton = oButtonEl;
6950                         }
6951     
6952                         if (Lang.isFunction(oButton.handler)) {
6953     
6954                             oYUIButton.set("onclick", { fn: oButton.handler, 
6955                                 obj: this, scope: this });
6956             
6957                         }
6958                         else if (Lang.isObject(oButton.handler) && 
6959                             Lang.isFunction(oButton.handler.fn)) {
6961                             oYUIButton.set("onclick", { fn: oButton.handler.fn, 
6962                                 obj: ((!Lang.isUndefined(oButton.handler.obj)) ? 
6963                                 oButton.handler.obj : this), 
6964                                 scope: (oButton.handler.scope || this) });
6965     
6966                         }
6968                         this._aButtons[this._aButtons.length] = oYUIButton;
6970                     }
6971                     else {
6972         
6973                         oButtonEl = document.createElement("button");
6974                         oButtonEl.setAttribute("type", "button");
6975             
6976                         if (oButton.isDefault) {
6977                             oButtonEl.className = "default";
6978                             this.defaultHtmlButton = oButtonEl;
6979                         }
6980     
6981                         oButtonEl.innerHTML = oButton.text;
6982     
6983                         if (Lang.isFunction(oButton.handler)) {
6984     
6985                             Event.on(oButtonEl, "click", oButton.handler, 
6986                                 this, true);
6987             
6988                         }
6989                         else if (Lang.isObject(oButton.handler) && 
6990                             Lang.isFunction(oButton.handler.fn)) {
6991     
6992                             Event.on(oButtonEl, "click", oButton.handler.fn, 
6993                                 ((!Lang.isUndefined(oButton.handler.obj)) ? 
6994                                 oButton.handler.obj : this), 
6995                                 (oButton.handler.scope || this));
6996     
6997                         }
6998             
6999                         oSpan.appendChild(oButtonEl);
7000                         
7001                         this._aButtons[this._aButtons.length] = oButtonEl;
7002                         
7003                     }
7005                     oButton.htmlButton = oButtonEl;
7006         
7007                     if (i === 0) {
7008                         this.firstButton = oButtonEl;
7009                     }
7010         
7011                     if (i == (nButtons - 1)) {
7012                         this.lastButton = oButtonEl;
7013                     }
7014         
7015                 }
7016         
7017                 this.setFooter(oSpan);
7019                 oFooter = this.footer;
7020                 
7021                 if (Dom.inDocument(this.element) && 
7022                     !Dom.isAncestor(oInnerElement, oFooter)) {
7023     
7024                     oInnerElement.appendChild(oFooter);
7025                 
7026                 }
7028                 this.buttonSpan = oSpan;
7030             } else { // Do cleanup
7032                 oSpan = this.buttonSpan;
7033                 oFooter = this.footer;
7035                 if (oSpan && oFooter) {
7037                     oFooter.removeChild(oSpan);
7039                     this.buttonSpan = null;
7040                     this.firstButton = null;
7041                     this.lastButton = null;
7042                     this.defaultHtmlButton = null;
7044                 }
7046             }
7048             this.cfg.refireEvent("iframe");
7049             this.cfg.refireEvent("underlay");
7051         },
7054         /**
7055         * @method getButtons
7056         * @description Returns an array containing each of the Dialog's 
7057         * buttons, by default an array of HTML <code>&#60;BUTTON&#60;</code> 
7058         * elements.  If the Dialog's buttons were created using the 
7059         * YAHOO.widget.Button class (via the inclusion of the optional Button 
7060         * dependancy on the page), an array of YAHOO.widget.Button instances 
7061         * is returned.
7062         * @return {Array}
7063         */
7064         getButtons: function () {
7065         
7066             var aButtons = this._aButtons;
7067             
7068             if (aButtons) {
7069             
7070                 return aButtons;
7071             
7072             }
7073         
7074         },
7076         
7077         /**
7078         * Sets focus to the first element in the Dialog's form or the first 
7079         * button defined via the "buttons" configuration property. Called 
7080         * when the Dialog is made visible.
7081         * @method focusFirst
7082         */
7083         focusFirst: function (type, args, obj) {
7084     
7085             var oElement = this.firstFormElement,
7086                 oEvent;
7088             if (args) {
7090                 oEvent = args[1];
7092                 if (oEvent) {
7094                     Event.stopEvent(oEvent);
7096                 }
7098             }
7099         
7101             if (oElement) {
7103                 /*
7104                     Place the call to the "focus" method inside a try/catch
7105                     block to prevent IE from throwing JavaScript errors if
7106                     the element is disabled or hidden.
7107                 */
7109                 try {
7111                     oElement.focus();
7113                 }
7114                 catch(oException) {
7116                 }
7118             } else {
7120                 this.focusDefaultButton();
7122             }
7124         },
7125         
7126         /**
7127         * Sets focus to the last element in the Dialog's form or the last 
7128         * button defined via the "buttons" configuration property.
7129         * @method focusLast
7130         */
7131         focusLast: function (type, args, obj) {
7132     
7133             var aButtons = this.cfg.getProperty("buttons"),
7134                 oElement = this.lastFormElement,
7135                 oEvent;
7136     
7137             if (args) {
7139                 oEvent = args[1];
7141                 if (oEvent) {
7143                     Event.stopEvent(oEvent);
7145                 }
7147             }
7148             
7149             if (aButtons && Lang.isArray(aButtons)) {
7151                 this.focusLastButton();
7153             } else {
7155                 if (oElement) {
7157                     /*
7158                         Place the call to the "focus" method inside a try/catch
7159                         block to prevent IE from throwing JavaScript errors if
7160                         the element is disabled or hidden.
7161                     */
7162     
7163                     try {
7164     
7165                         oElement.focus();
7166     
7167                     }
7168                     catch(oException) {
7169     
7170                     }
7172                 }
7174             }
7176         },
7177         
7178         /**
7179         * Sets the focus to the button that is designated as the default via 
7180         * the "buttons" configuration property. By default, this method is 
7181         * called when the Dialog is made visible.
7182         * @method focusDefaultButton
7183         */
7184         focusDefaultButton: function () {
7185         
7186             var oElement = this.defaultHtmlButton;
7187         
7188             if (oElement) {
7190                 /*
7191                     Place the call to the "focus" method inside a try/catch
7192                     block to prevent IE from throwing JavaScript errors if
7193                     the element is disabled or hidden.
7194                 */
7196                 try {
7198                     oElement.focus();
7199                 
7200                 }
7201                 catch(oException) {
7202                 
7203                 }
7205             }
7206         },
7207         
7208         /**
7209         * Blurs all the buttons defined via the "buttons" 
7210         * configuration property.
7211         * @method blurButtons
7212         */
7213         blurButtons: function () {
7214             
7215             var aButtons = this.cfg.getProperty("buttons"),
7216                 nButtons,
7217                 oButton,
7218                 oElement,
7219                 i;
7221             if (aButtons && Lang.isArray(aButtons)) {
7222             
7223                 nButtons = aButtons.length;
7224                 
7225                 if (nButtons > 0) {
7226                 
7227                     i = (nButtons - 1);
7228                     
7229                     do {
7230                     
7231                         oButton = aButtons[i];
7232                         
7233                         if (oButton) {
7235                             oElement = oButton.htmlButton;
7237                             if (oElement) {
7239                                 /*
7240                                     Place the call to the "blur" method inside  
7241                                     a try/catch block to prevent IE from  
7242                                     throwing JavaScript errors if the element 
7243                                     is disabled or hidden.
7244                                 */
7245     
7246                                 try {
7247             
7248                                     oElement.blur();
7249                                 
7250                                 }
7251                                 catch(oException) {
7252                                 
7253                                 
7254                                 }
7255                             
7256                             }
7258                         }
7259                     
7260                     }
7261                     while(i--);
7262                 
7263                 }
7264             
7265             }
7267         },
7268         
7269         /**
7270         * Sets the focus to the first button created via the "buttons"
7271         * configuration property.
7272         * @method focusFirstButton
7273         */
7274         focusFirstButton: function () {
7275     
7276             var aButtons = this.cfg.getProperty("buttons"),
7277                 oButton,
7278                 oElement;
7280             if (aButtons && Lang.isArray(aButtons)) {
7282                 oButton = aButtons[0];
7284                 if (oButton) {
7286                     oElement = oButton.htmlButton;
7287                     
7288                     if (oElement) {
7290                         /*
7291                             Place the call to the "focus" method inside a 
7292                             try/catch block to prevent IE from throwing 
7293                             JavaScript errors if the element is disabled 
7294                             or hidden.
7295                         */
7296     
7297                         try {
7298     
7299                             oElement.focus();
7300                         
7301                         }
7302                         catch(oException) {
7303                         
7304                         
7305                         }
7306                     
7307                     }
7309                 }
7311             }
7312         },
7313         
7314         /**
7315         * Sets the focus to the last button created via the "buttons" 
7316         * configuration property.
7317         * @method focusLastButton
7318         */
7319         focusLastButton: function () {
7320     
7321             var aButtons = this.cfg.getProperty("buttons"),
7322                 nButtons,
7323                 oButton,
7324                 oElement;
7326             if (aButtons && Lang.isArray(aButtons)) {
7328                 nButtons = aButtons.length;
7329                 
7330                 if (nButtons > 0) {
7332                     oButton = aButtons[(nButtons - 1)];
7333                     
7334                     if (oButton) {
7335                     
7336                         oElement = oButton.htmlButton;
7338                         if (oElement) {
7340                             /*
7341                                 Place the call to the "focus" method inside a 
7342                                 try/catch block to prevent IE from throwing 
7343                                 JavaScript errors if the element is disabled
7344                                 or hidden.
7345                             */
7346         
7347                             try {
7348         
7349                                 oElement.focus();
7350                             
7351                             }
7352                             catch(oException) {
7353                             
7354                             
7355                             }
7356                         
7357                         }
7358                     
7359                     }
7360                 
7361                 }
7362             
7363             }
7365         },
7366         
7367         /**
7368         * The default event handler for the "postmethod" configuration property
7369         * @method configPostMethod
7370         * @param {String} type The CustomEvent type (usually the property name)
7371         * @param {Object[]} args The CustomEvent arguments. For 
7372         * configuration handlers, args[0] will equal the newly applied value 
7373         * for the property.
7374         * @param {Object} obj The scope object. For configuration handlers, 
7375         * this will usually equal the owner.
7376         */
7377         configPostMethod: function (type, args, obj) {
7378     
7379             var postmethod = args[0];
7380         
7381             this.registerForm();
7382     
7383         },
7384         
7385         // END BUILT-IN PROPERTY EVENT HANDLERS //
7386         
7387         /**
7388         * Built-in function hook for writing a validation function that will 
7389         * be checked for a "true" value prior to a submit. This function, as 
7390         * implemented by default, always returns true, so it should be 
7391         * overridden if validation is necessary.
7392         * @method validate
7393         */
7394         validate: function () {
7395             return true;
7396         },
7397         
7398         /**
7399         * Executes a submit of the Dialog followed by a hide, if validation 
7400         * is successful.
7401         * @method submit
7402         */
7403         submit: function () {
7404             if (this.validate()) {
7405                 this.beforeSubmitEvent.fire();
7406                 this.doSubmit();
7407                 this.submitEvent.fire();
7408                 this.hide();
7409                 return true;
7410             } else {
7411                 return false;
7412             }
7413         },
7414         
7415         /**
7416         * Executes the cancel of the Dialog followed by a hide.
7417         * @method cancel
7418         */
7419         cancel: function () {
7420             this.cancelEvent.fire();
7421             this.hide();
7422         },
7423         
7424         /**
7425         * Returns a JSON-compatible data structure representing the data 
7426         * currently contained in the form.
7427         * @method getData
7428         * @return {Object} A JSON object reprsenting the data of the 
7429         * current form.
7430         */
7431         getData: function () {
7432         
7433             var oForm = this.form,
7434                 aElements,
7435                 nTotalElements,
7436                 oData,
7437                 sName,
7438                 oElement,
7439                 nElements,
7440                 sType,
7441                 sTagName,
7442                 aOptions,
7443                 nOptions,
7444                 aValues,
7445                 oOption,
7446                 sValue,
7447                 oRadio,
7448                 oCheckbox,
7449                 i,
7450                 n;    
7451     
7452             function isFormElement(p_oElement) {
7453             
7454                 var sTag = p_oElement.tagName.toUpperCase();
7455                 
7456                 return ((sTag == "INPUT" || sTag == "TEXTAREA" || 
7457                         sTag == "SELECT") && p_oElement.name == sName);
7458     
7459             }
7460     
7461     
7462             if (oForm) {
7463         
7464                 aElements = oForm.elements;
7465                 nTotalElements = aElements.length;
7466                 oData = {};
7467     
7468         
7469                 for (i = 0; i < nTotalElements; i++) {
7470         
7471                     sName = aElements[i].name;
7472         
7473                     /*
7474                         Using "Dom.getElementsBy" to safeguard user from JS 
7475                         errors that result from giving a form field (or set of 
7476                         fields) the same name as a native method of a form 
7477                         (like "submit") or a DOM collection (such as the "item"
7478                         method). Originally tried accessing fields via the 
7479                         "namedItem" method of the "element" collection, but 
7480                         discovered that it won't return a collection of fields 
7481                         in Gecko.
7482                     */
7483         
7484                     oElement = Dom.getElementsBy(isFormElement, "*", oForm);
7485                     nElements = oElement.length;
7486         
7487                     if (nElements > 0) {
7488         
7489                         if (nElements == 1) {
7490         
7491                             oElement = oElement[0];
7492         
7493                             sType = oElement.type;
7494                             sTagName = oElement.tagName.toUpperCase();
7495         
7496                             switch (sTagName) {
7497         
7498                             case "INPUT":
7499     
7500                                 if (sType == "checkbox") {
7501     
7502                                     oData[sName] = oElement.checked;
7503     
7504                                 }
7505                                 else if (sType != "radio") {
7506     
7507                                     oData[sName] = oElement.value;
7508     
7509                                 }
7510     
7511                                 break;
7512     
7513                             case "TEXTAREA":
7514     
7515                                 oData[sName] = oElement.value;
7516     
7517                                 break;
7518     
7519                             case "SELECT":
7520     
7521                                 aOptions = oElement.options;
7522                                 nOptions = aOptions.length;
7523                                 aValues = [];
7524     
7525                                 for (n = 0; n < nOptions; n++) {
7526     
7527                                     oOption = aOptions[n];
7528     
7529                                     if (oOption.selected) {
7530     
7531                                         sValue = oOption.value;
7532     
7533                                         if (!sValue || sValue === "") {
7534     
7535                                             sValue = oOption.text;
7536     
7537                                         }
7538     
7539                                         aValues[aValues.length] = sValue;
7540     
7541                                     }
7542     
7543                                 }
7544     
7545                                 oData[sName] = aValues;
7546     
7547                                 break;
7548         
7549                             }
7550         
7551         
7552                         }
7553                         else {
7554         
7555                             sType = oElement[0].type;
7556         
7557                             switch (sType) {
7558         
7559                             case "radio":
7560     
7561                                 for (n = 0; n < nElements; n++) {
7562     
7563                                     oRadio = oElement[n];
7564     
7565                                     if (oRadio.checked) {
7566     
7567                                         oData[sName] = oRadio.value;
7568                                         break;
7569     
7570                                     }
7571     
7572                                 }
7573     
7574                                 break;
7575     
7576                             case "checkbox":
7577     
7578                                 aValues = [];
7579     
7580                                 for (n = 0; n < nElements; n++) {
7581     
7582                                     oCheckbox = oElement[n];
7583     
7584                                     if (oCheckbox.checked) {
7585     
7586                                         aValues[aValues.length] = 
7587                                             oCheckbox.value;
7588     
7589                                     }
7590     
7591                                 }
7592     
7593                                 oData[sName] = aValues;
7594     
7595                                 break;
7596         
7597                             }
7598         
7599                         }
7600         
7601                     }
7602         
7603                 }
7604         
7605             }
7606         
7607         
7608             return oData;
7609         
7610         },
7611         
7612         /**
7613         * Removes the Panel element from the DOM and sets all child elements 
7614         * to null.
7615         * @method destroy
7616         */
7617         destroy: function () {
7618         
7619             removeButtonEventHandlers.call(this);
7620             
7621             this._aButtons = null;
7623             var aForms = this.element.getElementsByTagName("form"),
7624                 oForm;
7625             
7626             if (aForms.length > 0) {
7628                 oForm = aForms[0];
7630                 if (oForm) {
7631                    
7632                     Event.purgeElement(oForm);
7633             
7634                     this.body.removeChild(oForm);
7635                     
7636                     this.form = null;
7637             
7638                 }
7639             
7640             }
7641         
7642             Dialog.superclass.destroy.call(this);  
7643         
7644         },
7645         
7646         /**
7647         * Returns a string representation of the object.
7648         * @method toString
7649         * @return {String} The string representation of the Dialog
7650         */
7651         toString: function () {
7652             return "Dialog " + this.id;
7653         }
7654     
7655     });
7657 }());
7658 (function () {
7660     /**
7661     * SimpleDialog is a simple implementation of Dialog that can be used to 
7662     * submit a single value. Forms can be processed in 3 ways -- via an 
7663     * asynchronous Connection utility call, a simple form POST or GET, 
7664     * or manually.
7665     * @namespace YAHOO.widget
7666     * @class SimpleDialog
7667     * @extends YAHOO.widget.Dialog
7668     * @constructor
7669     * @param {String} el The element ID representing the SimpleDialog 
7670     * <em>OR</em>
7671     * @param {HTMLElement} el The element representing the SimpleDialog
7672     * @param {Object} userConfig The configuration object literal containing 
7673     * the configuration that should be set for this SimpleDialog. See 
7674     * configuration documentation for more details.
7675     */
7676     YAHOO.widget.SimpleDialog = function (el, userConfig) {
7677     
7678         YAHOO.widget.SimpleDialog.superclass.constructor.call(this, 
7679             el, userConfig);
7680     
7681     };
7683     var Dom = YAHOO.util.Dom,
7684         SimpleDialog = YAHOO.widget.SimpleDialog,
7685     
7686         /**
7687         * Constant representing the SimpleDialog's configuration properties
7688         * @property DEFAULT_CONFIG
7689         * @private
7690         * @final
7691         * @type Object
7692         */
7693         DEFAULT_CONFIG = {
7694         
7695             "ICON": { 
7696                 key: "icon", 
7697                 value: "none", 
7698                 suppressEvent: true  
7699             },
7700         
7701             "TEXT": { 
7702                 key: "text", 
7703                 value: "", 
7704                 suppressEvent: true, 
7705                 supercedes: ["icon"] 
7706             }
7707         
7708         };
7710     /**
7711     * Constant for the standard network icon for a blocking action
7712     * @property YAHOO.widget.SimpleDialog.ICON_BLOCK
7713     * @static
7714     * @final
7715     * @type String
7716     */
7717     SimpleDialog.ICON_BLOCK = "blckicon";
7718     
7719     /**
7720     * Constant for the standard network icon for alarm
7721     * @property YAHOO.widget.SimpleDialog.ICON_ALARM
7722     * @static
7723     * @final
7724     * @type String
7725     */
7726     SimpleDialog.ICON_ALARM = "alrticon";
7727     
7728     /**
7729     * Constant for the standard network icon for help
7730     * @property YAHOO.widget.SimpleDialog.ICON_HELP
7731     * @static
7732     * @final
7733     * @type String
7734     */
7735     SimpleDialog.ICON_HELP  = "hlpicon";
7736     
7737     /**
7738     * Constant for the standard network icon for info
7739     * @property YAHOO.widget.SimpleDialog.ICON_INFO
7740     * @static
7741     * @final
7742     * @type String
7743     */
7744     SimpleDialog.ICON_INFO  = "infoicon";
7745     
7746     /**
7747     * Constant for the standard network icon for warn
7748     * @property YAHOO.widget.SimpleDialog.ICON_WARN
7749     * @static
7750     * @final
7751     * @type String
7752     */
7753     SimpleDialog.ICON_WARN  = "warnicon";
7754     
7755     /**
7756     * Constant for the standard network icon for a tip
7757     * @property YAHOO.widget.SimpleDialog.ICON_TIP
7758     * @static
7759     * @final
7760     * @type String
7761     */
7762     SimpleDialog.ICON_TIP   = "tipicon";
7764     /**
7765     * Constant representing the name of the CSS class applied to the element 
7766     * created by the "icon" configuration property.
7767     * @property YAHOO.widget.SimpleDialog.ICON_CSS_CLASSNAME
7768     * @static
7769     * @final
7770     * @type String
7771     */
7772     SimpleDialog.ICON_CSS_CLASSNAME = "yui-icon";
7773     
7774     /**
7775     * Constant representing the default CSS class used for a SimpleDialog
7776     * @property YAHOO.widget.SimpleDialog.CSS_SIMPLEDIALOG
7777     * @static
7778     * @final
7779     * @type String
7780     */
7781     SimpleDialog.CSS_SIMPLEDIALOG = "yui-simple-dialog";
7783     
7784     YAHOO.extend(SimpleDialog, YAHOO.widget.Dialog, {
7785     
7786         /**
7787         * Initializes the class's configurable properties which can be changed 
7788         * using the SimpleDialog's Config object (cfg).
7789         * @method initDefaultConfig
7790         */
7791         initDefaultConfig: function () {
7792         
7793             SimpleDialog.superclass.initDefaultConfig.call(this);
7794         
7795             // Add dialog config properties //
7796         
7797             /**
7798             * Sets the informational icon for the SimpleDialog
7799             * @config icon
7800             * @type String
7801             * @default "none"
7802             */
7803             this.cfg.addProperty(DEFAULT_CONFIG.ICON.key, {
7804                 handler: this.configIcon,
7805                 value: DEFAULT_CONFIG.ICON.value,
7806                 suppressEvent: DEFAULT_CONFIG.ICON.suppressEvent
7807             });
7808         
7809             /**
7810             * Sets the text for the SimpleDialog
7811             * @config text
7812             * @type String
7813             * @default ""
7814             */
7815             this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, { 
7816                 handler: this.configText, 
7817                 value: DEFAULT_CONFIG.TEXT.value, 
7818                 suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent, 
7819                 supercedes: DEFAULT_CONFIG.TEXT.supercedes 
7820             });
7821         
7822         },
7823         
7824         
7825         /**
7826         * The SimpleDialog initialization method, which is executed for 
7827         * SimpleDialog and all of its subclasses. This method is automatically 
7828         * called by the constructor, and  sets up all DOM references for 
7829         * pre-existing markup, and creates required markup if it is not 
7830         * already present.
7831         * @method init
7832         * @param {String} el The element ID representing the SimpleDialog 
7833         * <em>OR</em>
7834         * @param {HTMLElement} el The element representing the SimpleDialog
7835         * @param {Object} userConfig The configuration object literal 
7836         * containing the configuration that should be set for this 
7837         * SimpleDialog. See configuration documentation for more details.
7838         */
7839         init: function (el, userConfig) {
7841             /*
7842                 Note that we don't pass the user config in here yet because we 
7843                 only want it executed once, at the lowest subclass level
7844             */
7846             SimpleDialog.superclass.init.call(this, el/*, userConfig*/);
7847         
7848             this.beforeInitEvent.fire(SimpleDialog);
7849         
7850             Dom.addClass(this.element, SimpleDialog.CSS_SIMPLEDIALOG);
7851         
7852             this.cfg.queueProperty("postmethod", "manual");
7853         
7854             if (userConfig) {
7855                 this.cfg.applyConfig(userConfig, true);
7856             }
7857         
7858             this.beforeRenderEvent.subscribe(function () {
7859                 if (! this.body) {
7860                     this.setBody("");
7861                 }
7862             }, this, true);
7863         
7864             this.initEvent.fire(SimpleDialog);
7865         
7866         },
7867         
7868         /**
7869         * Prepares the SimpleDialog's internal FORM object, creating one if one 
7870         * is not currently present, and adding the value hidden field.
7871         * @method registerForm
7872         */
7873         registerForm: function () {
7875             SimpleDialog.superclass.registerForm.call(this);
7877             this.form.innerHTML += "<input type=\"hidden\" name=\"" + 
7878                 this.id + "\" value=\"\"/>";
7880         },
7881         
7882         // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
7883         
7884         /**
7885         * Fired when the "icon" property is set.
7886         * @method configIcon
7887         * @param {String} type The CustomEvent type (usually the property name)
7888         * @param {Object[]} args The CustomEvent arguments. For configuration 
7889         * handlers, args[0] will equal the newly applied value for the property.
7890         * @param {Object} obj The scope object. For configuration handlers, 
7891         * this will usually equal the owner.
7892         */
7893         configIcon: function (type,args,obj) {
7894         
7895             var sIcon = args[0],
7896                 oBody = this.body,
7897                 sCSSClass = SimpleDialog.ICON_CSS_CLASSNAME,
7898                 oIcon,
7899                 oIconParent;
7900         
7901             if (sIcon && sIcon != "none") {
7903                 oIcon = Dom.getElementsByClassName(sCSSClass, "*" , oBody);
7905                 if (oIcon) {
7907                     oIconParent = oIcon.parentNode;
7908                     
7909                     if (oIconParent) {
7910                     
7911                         oIconParent.removeChild(oIcon);
7912                         
7913                         oIcon = null;
7914                     
7915                     }
7917                 }
7920                 if (sIcon.indexOf(".") == -1) {
7922                     oIcon = document.createElement("span");
7923                     oIcon.className = (sCSSClass + " " + sIcon);
7924                     oIcon.innerHTML = "&#160;";
7926                 } else {
7928                     oIcon = document.createElement("img");
7929                     oIcon.src = (this.imageRoot + sIcon);
7930                     oIcon.className = sCSSClass;
7932                 }
7933                 
7935                 if (oIcon) {
7936                 
7937                     oBody.insertBefore(oIcon, oBody.firstChild);
7938                 
7939                 }
7941             }
7943         },
7944         
7945         /**
7946         * Fired when the "text" property is set.
7947         * @method configText
7948         * @param {String} type The CustomEvent type (usually the property name)
7949         * @param {Object[]} args The CustomEvent arguments. For configuration 
7950         * handlers, args[0] will equal the newly applied value for the property.
7951         * @param {Object} obj The scope object. For configuration handlers, 
7952         * this will usually equal the owner.
7953         */
7954         configText: function (type,args,obj) {
7955             var text = args[0];
7956             if (text) {
7957                 this.setBody(text);
7958                 this.cfg.refireEvent("icon");
7959             }
7960         },
7961         
7962         // END BUILT-IN PROPERTY EVENT HANDLERS //
7963         
7964         /**
7965         * Returns a string representation of the object.
7966         * @method toString
7967         * @return {String} The string representation of the SimpleDialog
7968         */
7969         toString: function () {
7970             return "SimpleDialog " + this.id;
7971         }
7972     
7973     });
7975 }());
7976 (function () {
7978     /**
7979     * ContainerEffect encapsulates animation transitions that are executed when 
7980     * an Overlay is shown or hidden.
7981     * @namespace YAHOO.widget
7982     * @class ContainerEffect
7983     * @constructor
7984     * @param {YAHOO.widget.Overlay} overlay The Overlay that the animation 
7985     * should be associated with
7986     * @param {Object} attrIn The object literal representing the animation 
7987     * arguments to be used for the animate-in transition. The arguments for 
7988     * this literal are: attributes(object, see YAHOO.util.Anim for description), 
7989     * duration(Number), and method(i.e. Easing.easeIn).
7990     * @param {Object} attrOut The object literal representing the animation 
7991     * arguments to be used for the animate-out transition. The arguments for  
7992     * this literal are: attributes(object, see YAHOO.util.Anim for description), 
7993     * duration(Number), and method(i.e. Easing.easeIn).
7994     * @param {HTMLElement} targetElement Optional. The target element that  
7995     * should be animated during the transition. Defaults to overlay.element.
7996     * @param {class} Optional. The animation class to instantiate. Defaults to 
7997     * YAHOO.util.Anim. Other options include YAHOO.util.Motion.
7998     */
7999     YAHOO.widget.ContainerEffect = 
8000     
8001         function (overlay, attrIn, attrOut, targetElement, animClass) {
8002     
8003         if (!animClass) {
8004             animClass = YAHOO.util.Anim;
8005         }
8006         
8007         /**
8008         * The overlay to animate
8009         * @property overlay
8010         * @type YAHOO.widget.Overlay
8011         */
8012         this.overlay = overlay;
8013     
8014         /**
8015         * The animation attributes to use when transitioning into view
8016         * @property attrIn
8017         * @type Object
8018         */
8019         this.attrIn = attrIn;
8020     
8021         /**
8022         * The animation attributes to use when transitioning out of view
8023         * @property attrOut
8024         * @type Object
8025         */
8026         this.attrOut = attrOut;
8027     
8028         /**
8029         * The target element to be animated
8030         * @property targetElement
8031         * @type HTMLElement
8032         */
8033         this.targetElement = targetElement || overlay.element;
8034     
8035         /**
8036         * The animation class to use for animating the overlay
8037         * @property animClass
8038         * @type class
8039         */
8040         this.animClass = animClass;
8041     
8042     };
8045     var Dom = YAHOO.util.Dom,
8046         CustomEvent = YAHOO.util.CustomEvent,
8047         Easing = YAHOO.util.Easing,
8048         ContainerEffect = YAHOO.widget.ContainerEffect;
8051     /**
8052     * A pre-configured ContainerEffect instance that can be used for fading 
8053     * an overlay in and out.
8054     * @method FADE
8055     * @static
8056     * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
8057     * @param {Number} dur The duration of the animation
8058     * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
8059     */
8060     ContainerEffect.FADE = function (overlay, dur) {
8061     
8062         var fade = new ContainerEffect(overlay, 
8063         
8064             { attributes: { opacity: { from: 0, to: 1 } }, 
8065                 duration: dur, 
8066                 method: Easing.easeIn }, 
8067             
8068             { attributes: { opacity: { to: 0 } },
8069                 duration: dur, 
8070                 method: Easing.easeOut }, 
8071             
8072             overlay.element);
8073         
8074     
8075         fade.handleStartAnimateIn = function (type,args,obj) {
8076             Dom.addClass(obj.overlay.element, "hide-select");
8077         
8078             if (! obj.overlay.underlay) {
8079                 obj.overlay.cfg.refireEvent("underlay");
8080             }
8081         
8082             if (obj.overlay.underlay) {
8083     
8084                 obj.initialUnderlayOpacity = 
8085                     Dom.getStyle(obj.overlay.underlay, "opacity");
8086     
8087                 obj.overlay.underlay.style.filter = null;
8088     
8089             }
8090         
8091             Dom.setStyle(obj.overlay.element, "visibility", "visible");
8092             Dom.setStyle(obj.overlay.element, "opacity", 0);
8093         };
8094         
8095     
8096         fade.handleCompleteAnimateIn = function (type,args,obj) {
8097             Dom.removeClass(obj.overlay.element, "hide-select");
8098         
8099             if (obj.overlay.element.style.filter) {
8100                 obj.overlay.element.style.filter = null;
8101             }
8102         
8103             if (obj.overlay.underlay) {
8104                 Dom.setStyle(obj.overlay.underlay, "opacity", 
8105                     obj.initialUnderlayOpacity);
8106             }
8107         
8108             obj.overlay.cfg.refireEvent("iframe");
8109             obj.animateInCompleteEvent.fire();
8110         };
8111         
8112     
8113         fade.handleStartAnimateOut = function (type, args, obj) {
8114             Dom.addClass(obj.overlay.element, "hide-select");
8115         
8116             if (obj.overlay.underlay) {
8117                 obj.overlay.underlay.style.filter = null;
8118             }
8119         };
8120         
8121     
8122         fade.handleCompleteAnimateOut =  function (type, args, obj) {
8123             Dom.removeClass(obj.overlay.element, "hide-select");
8124             if (obj.overlay.element.style.filter) {
8125                 obj.overlay.element.style.filter = null;
8126             }
8127             Dom.setStyle(obj.overlay.element, "visibility", "hidden");
8128             Dom.setStyle(obj.overlay.element, "opacity", 1);
8129         
8130             obj.overlay.cfg.refireEvent("iframe");
8131         
8132             obj.animateOutCompleteEvent.fire();
8133         };
8134         
8135         fade.init();
8136         return fade;
8137     };
8138     
8139     
8140     /**
8141     * A pre-configured ContainerEffect instance that can be used for sliding an 
8142     * overlay in and out.
8143     * @method SLIDE
8144     * @static
8145     * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
8146     * @param {Number} dur The duration of the animation
8147     * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
8148     */
8149     ContainerEffect.SLIDE = function (overlay, dur) {
8150     
8151         var x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
8152     
8153             y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
8154     
8155             clientWidth = Dom.getClientWidth(),
8156     
8157             offsetWidth = overlay.element.offsetWidth,
8158     
8159             slide = new ContainerEffect(overlay, 
8160             
8161             { attributes: { points: { to: [x, y] } },
8162                 duration: dur,
8163                 method: Easing.easeIn },
8164     
8165             { attributes: { points: { to: [(clientWidth + 25), y] } },
8166                 duration: dur,
8167                 method: Easing.easeOut },
8168     
8169             overlay.element, YAHOO.util.Motion);
8170         
8171         
8172         slide.handleStartAnimateIn = function (type,args,obj) {
8173             obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
8174             obj.overlay.element.style.top  = y + "px";
8175         };
8176         
8177         slide.handleTweenAnimateIn = function (type, args, obj) {
8178         
8179             var pos = Dom.getXY(obj.overlay.element),
8180                 currentX = pos[0],
8181                 currentY = pos[1];
8182         
8183             if (Dom.getStyle(obj.overlay.element, "visibility") == 
8184                 "hidden" && currentX < x) {
8186                 Dom.setStyle(obj.overlay.element, "visibility", "visible");
8188             }
8189         
8190             obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
8191             obj.overlay.cfg.refireEvent("iframe");
8192         };
8193         
8194         slide.handleCompleteAnimateIn = function (type, args, obj) {
8195             obj.overlay.cfg.setProperty("xy", [x, y], true);
8196             obj.startX = x;
8197             obj.startY = y;
8198             obj.overlay.cfg.refireEvent("iframe");
8199             obj.animateInCompleteEvent.fire();
8200         };
8201         
8202         slide.handleStartAnimateOut = function (type, args, obj) {
8203     
8204             var vw = Dom.getViewportWidth(),
8205                 pos = Dom.getXY(obj.overlay.element),
8206                 yso = pos[1],
8207                 currentTo = obj.animOut.attributes.points.to;
8208     
8209             obj.animOut.attributes.points.to = [(vw + 25), yso];
8210     
8211         };
8212         
8213         slide.handleTweenAnimateOut = function (type, args, obj) {
8214     
8215             var pos = Dom.getXY(obj.overlay.element),
8216                 xto = pos[0],
8217                 yto = pos[1];
8218         
8219             obj.overlay.cfg.setProperty("xy", [xto, yto], true);
8220             obj.overlay.cfg.refireEvent("iframe");
8221         };
8222         
8223         slide.handleCompleteAnimateOut = function (type, args, obj) {
8224             Dom.setStyle(obj.overlay.element, "visibility", "hidden");
8225         
8226             obj.overlay.cfg.setProperty("xy", [x, y]);
8227             obj.animateOutCompleteEvent.fire();
8228         };
8229         
8230         slide.init();
8231         return slide;
8232     };
8233     
8234     ContainerEffect.prototype = {
8235     
8236         /**
8237         * Initializes the animation classes and events.
8238         * @method init
8239         */
8240         init: function () {
8242             this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
8243             this.beforeAnimateInEvent.signature = CustomEvent.LIST;
8244             
8245             this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
8246             this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
8247         
8248             this.animateInCompleteEvent = this.createEvent("animateInComplete");
8249             this.animateInCompleteEvent.signature = CustomEvent.LIST;
8250         
8251             this.animateOutCompleteEvent = 
8252                 this.createEvent("animateOutComplete");
8253             this.animateOutCompleteEvent.signature = CustomEvent.LIST;
8254         
8255             this.animIn = new this.animClass(this.targetElement, 
8256                 this.attrIn.attributes, this.attrIn.duration, 
8257                 this.attrIn.method);
8259             this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
8260             this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
8262             this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn, 
8263                 this);
8264         
8265             this.animOut = new this.animClass(this.targetElement, 
8266                 this.attrOut.attributes, this.attrOut.duration, 
8267                 this.attrOut.method);
8269             this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
8270             this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
8271             this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut, 
8272                 this);
8274         },
8275         
8276         /**
8277         * Triggers the in-animation.
8278         * @method animateIn
8279         */
8280         animateIn: function () {
8281             this.beforeAnimateInEvent.fire();
8282             this.animIn.animate();
8283         },
8284         
8285         /**
8286         * Triggers the out-animation.
8287         * @method animateOut
8288         */
8289         animateOut: function () {
8290             this.beforeAnimateOutEvent.fire();
8291             this.animOut.animate();
8292         },
8293         
8294         /**
8295         * The default onStart handler for the in-animation.
8296         * @method handleStartAnimateIn
8297         * @param {String} type The CustomEvent type
8298         * @param {Object[]} args The CustomEvent arguments
8299         * @param {Object} obj The scope object
8300         */
8301         handleStartAnimateIn: function (type, args, obj) { },
8302     
8303         /**
8304         * The default onTween handler for the in-animation.
8305         * @method handleTweenAnimateIn
8306         * @param {String} type The CustomEvent type
8307         * @param {Object[]} args The CustomEvent arguments
8308         * @param {Object} obj The scope object
8309         */
8310         handleTweenAnimateIn: function (type, args, obj) { },
8311     
8312         /**
8313         * The default onComplete handler for the in-animation.
8314         * @method handleCompleteAnimateIn
8315         * @param {String} type The CustomEvent type
8316         * @param {Object[]} args The CustomEvent arguments
8317         * @param {Object} obj The scope object
8318         */
8319         handleCompleteAnimateIn: function (type, args, obj) { },
8320         
8321         /**
8322         * The default onStart handler for the out-animation.
8323         * @method handleStartAnimateOut
8324         * @param {String} type The CustomEvent type
8325         * @param {Object[]} args The CustomEvent arguments
8326         * @param {Object} obj The scope object
8327         */
8328         handleStartAnimateOut: function (type, args, obj) { },
8329     
8330         /**
8331         * The default onTween handler for the out-animation.
8332         * @method handleTweenAnimateOut
8333         * @param {String} type The CustomEvent type
8334         * @param {Object[]} args The CustomEvent arguments
8335         * @param {Object} obj The scope object
8336         */
8337         handleTweenAnimateOut: function (type, args, obj) { },
8338     
8339         /**
8340         * The default onComplete handler for the out-animation.
8341         * @method handleCompleteAnimateOut
8342         * @param {String} type The CustomEvent type
8343         * @param {Object[]} args The CustomEvent arguments
8344         * @param {Object} obj The scope object
8345         */
8346         handleCompleteAnimateOut: function (type, args, obj) { },
8347         
8348         /**
8349         * Returns a string representation of the object.
8350         * @method toString
8351         * @return {String} The string representation of the ContainerEffect
8352         */
8353         toString: function () {
8354             var output = "ContainerEffect";
8355             if (this.overlay) {
8356                 output += " [" + this.overlay.toString() + "]";
8357             }
8358             return output;
8359         }
8360     
8361     };
8363     YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
8365 })();
8366 YAHOO.register("container", YAHOO.widget.Module, {version: "2.3.0", build: "442"});