]> ToastFreeware Gitweb - philipp/winterrodeln/wradmin.git/blobdiff - wradmin/static/yui/container/container.js
Rename public directory to static.
[philipp/winterrodeln/wradmin.git] / wradmin / static / yui / container / container.js
diff --git a/wradmin/static/yui/container/container.js b/wradmin/static/yui/container/container.js
new file mode 100644 (file)
index 0000000..620e954
--- /dev/null
@@ -0,0 +1,9064 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.7.0
+*/
+(function () {
+
+    /**
+    * Config is a utility used within an Object to allow the implementer to
+    * maintain a list of local configuration properties and listen for changes 
+    * to those properties dynamically using CustomEvent. The initial values are 
+    * also maintained so that the configuration can be reset at any given point 
+    * to its initial state.
+    * @namespace YAHOO.util
+    * @class Config
+    * @constructor
+    * @param {Object} owner The owner Object to which this Config Object belongs
+    */
+    YAHOO.util.Config = function (owner) {
+
+        if (owner) {
+            this.init(owner);
+        }
+
+
+    };
+
+
+    var Lang = YAHOO.lang,
+        CustomEvent = YAHOO.util.CustomEvent,
+        Config = YAHOO.util.Config;
+
+
+    /**
+     * Constant representing the CustomEvent type for the config changed event.
+     * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
+     * @private
+     * @static
+     * @final
+     */
+    Config.CONFIG_CHANGED_EVENT = "configChanged";
+    
+    /**
+     * Constant representing the boolean type string
+     * @property YAHOO.util.Config.BOOLEAN_TYPE
+     * @private
+     * @static
+     * @final
+     */
+    Config.BOOLEAN_TYPE = "boolean";
+    
+    Config.prototype = {
+     
+        /**
+        * Object reference to the owner of this Config Object
+        * @property owner
+        * @type Object
+        */
+        owner: null,
+        
+        /**
+        * Boolean flag that specifies whether a queue is currently 
+        * being executed
+        * @property queueInProgress
+        * @type Boolean
+        */
+        queueInProgress: false,
+        
+        /**
+        * Maintains the local collection of configuration property objects and 
+        * their specified values
+        * @property config
+        * @private
+        * @type Object
+        */ 
+        config: null,
+        
+        /**
+        * Maintains the local collection of configuration property objects as 
+        * they were initially applied.
+        * This object is used when resetting a property.
+        * @property initialConfig
+        * @private
+        * @type Object
+        */ 
+        initialConfig: null,
+        
+        /**
+        * Maintains the local, normalized CustomEvent queue
+        * @property eventQueue
+        * @private
+        * @type Object
+        */ 
+        eventQueue: null,
+        
+        /**
+        * Custom Event, notifying subscribers when Config properties are set 
+        * (setProperty is called without the silent flag
+        * @event configChangedEvent
+        */
+        configChangedEvent: null,
+    
+        /**
+        * Initializes the configuration Object and all of its local members.
+        * @method init
+        * @param {Object} owner The owner Object to which this Config 
+        * Object belongs
+        */
+        init: function (owner) {
+    
+            this.owner = owner;
+    
+            this.configChangedEvent = 
+                this.createEvent(Config.CONFIG_CHANGED_EVENT);
+    
+            this.configChangedEvent.signature = CustomEvent.LIST;
+            this.queueInProgress = false;
+            this.config = {};
+            this.initialConfig = {};
+            this.eventQueue = [];
+        
+        },
+        
+        /**
+        * Validates that the value passed in is a Boolean.
+        * @method checkBoolean
+        * @param {Object} val The value to validate
+        * @return {Boolean} true, if the value is valid
+        */ 
+        checkBoolean: function (val) {
+            return (typeof val == Config.BOOLEAN_TYPE);
+        },
+        
+        /**
+        * Validates that the value passed in is a number.
+        * @method checkNumber
+        * @param {Object} val The value to validate
+        * @return {Boolean} true, if the value is valid
+        */
+        checkNumber: function (val) {
+            return (!isNaN(val));
+        },
+        
+        /**
+        * Fires a configuration property event using the specified value. 
+        * @method fireEvent
+        * @private
+        * @param {String} key The configuration property's name
+        * @param {value} Object The value of the correct type for the property
+        */ 
+        fireEvent: function ( key, value ) {
+            var property = this.config[key];
+        
+            if (property && property.event) {
+                property.event.fire(value);
+            } 
+        },
+        
+        /**
+        * Adds a property to the Config Object's private config hash.
+        * @method addProperty
+        * @param {String} key The configuration property's name
+        * @param {Object} propertyObject The Object containing all of this 
+        * property's arguments
+        */
+        addProperty: function ( key, propertyObject ) {
+            key = key.toLowerCase();
+        
+            this.config[key] = propertyObject;
+        
+            propertyObject.event = this.createEvent(key, { scope: this.owner });
+            propertyObject.event.signature = CustomEvent.LIST;
+            
+            
+            propertyObject.key = key;
+        
+            if (propertyObject.handler) {
+                propertyObject.event.subscribe(propertyObject.handler, 
+                    this.owner);
+            }
+        
+            this.setProperty(key, propertyObject.value, true);
+            
+            if (! propertyObject.suppressEvent) {
+                this.queueProperty(key, propertyObject.value);
+            }
+            
+        },
+        
+        /**
+        * Returns a key-value configuration map of the values currently set in  
+        * the Config Object.
+        * @method getConfig
+        * @return {Object} The current config, represented in a key-value map
+        */
+        getConfig: function () {
+        
+            var cfg = {},
+                currCfg = this.config,
+                prop,
+                property;
+                
+            for (prop in currCfg) {
+                if (Lang.hasOwnProperty(currCfg, prop)) {
+                    property = currCfg[prop];
+                    if (property && property.event) {
+                        cfg[prop] = property.value;
+                    }
+                }
+            }
+
+            return cfg;
+        },
+        
+        /**
+        * Returns the value of specified property.
+        * @method getProperty
+        * @param {String} key The name of the property
+        * @return {Object}  The value of the specified property
+        */
+        getProperty: function (key) {
+            var property = this.config[key.toLowerCase()];
+            if (property && property.event) {
+                return property.value;
+            } else {
+                return undefined;
+            }
+        },
+        
+        /**
+        * Resets the specified property's value to its initial value.
+        * @method resetProperty
+        * @param {String} key The name of the property
+        * @return {Boolean} True is the property was reset, false if not
+        */
+        resetProperty: function (key) {
+    
+            key = key.toLowerCase();
+        
+            var property = this.config[key];
+    
+            if (property && property.event) {
+    
+                if (this.initialConfig[key] && 
+                    !Lang.isUndefined(this.initialConfig[key])) {
+    
+                    this.setProperty(key, this.initialConfig[key]);
+
+                    return true;
+    
+                }
+    
+            } else {
+    
+                return false;
+            }
+    
+        },
+        
+        /**
+        * Sets the value of a property. If the silent property is passed as 
+        * true, the property's event will not be fired.
+        * @method setProperty
+        * @param {String} key The name of the property
+        * @param {String} value The value to set the property to
+        * @param {Boolean} silent Whether the value should be set silently, 
+        * without firing the property event.
+        * @return {Boolean} True, if the set was successful, false if it failed.
+        */
+        setProperty: function (key, value, silent) {
+        
+            var property;
+        
+            key = key.toLowerCase();
+        
+            if (this.queueInProgress && ! silent) {
+                // Currently running through a queue... 
+                this.queueProperty(key,value);
+                return true;
+    
+            } else {
+                property = this.config[key];
+                if (property && property.event) {
+                    if (property.validator && !property.validator(value)) {
+                        return false;
+                    } else {
+                        property.value = value;
+                        if (! silent) {
+                            this.fireEvent(key, value);
+                            this.configChangedEvent.fire([key, value]);
+                        }
+                        return true;
+                    }
+                } else {
+                    return false;
+                }
+            }
+        },
+        
+        /**
+        * Sets the value of a property and queues its event to execute. If the 
+        * event is already scheduled to execute, it is
+        * moved from its current position to the end of the queue.
+        * @method queueProperty
+        * @param {String} key The name of the property
+        * @param {String} value The value to set the property to
+        * @return {Boolean}  true, if the set was successful, false if 
+        * it failed.
+        */ 
+        queueProperty: function (key, value) {
+        
+            key = key.toLowerCase();
+        
+            var property = this.config[key],
+                foundDuplicate = false,
+                iLen,
+                queueItem,
+                queueItemKey,
+                queueItemValue,
+                sLen,
+                supercedesCheck,
+                qLen,
+                queueItemCheck,
+                queueItemCheckKey,
+                queueItemCheckValue,
+                i,
+                s,
+                q;
+                                
+            if (property && property.event) {
+    
+                if (!Lang.isUndefined(value) && property.validator && 
+                    !property.validator(value)) { // validator
+                    return false;
+                } else {
+        
+                    if (!Lang.isUndefined(value)) {
+                        property.value = value;
+                    } else {
+                        value = property.value;
+                    }
+        
+                    foundDuplicate = false;
+                    iLen = this.eventQueue.length;
+        
+                    for (i = 0; i < iLen; i++) {
+                        queueItem = this.eventQueue[i];
+        
+                        if (queueItem) {
+                            queueItemKey = queueItem[0];
+                            queueItemValue = queueItem[1];
+
+                            if (queueItemKey == key) {
+    
+                                /*
+                                    found a dupe... push to end of queue, null 
+                                    current item, and break
+                                */
+    
+                                this.eventQueue[i] = null;
+    
+                                this.eventQueue.push(
+                                    [key, (!Lang.isUndefined(value) ? 
+                                    value : queueItemValue)]);
+    
+                                foundDuplicate = true;
+                                break;
+                            }
+                        }
+                    }
+                    
+                    // this is a refire, or a new property in the queue
+    
+                    if (! foundDuplicate && !Lang.isUndefined(value)) { 
+                        this.eventQueue.push([key, value]);
+                    }
+                }
+        
+                if (property.supercedes) {
+
+                    sLen = property.supercedes.length;
+
+                    for (s = 0; s < sLen; s++) {
+
+                        supercedesCheck = property.supercedes[s];
+                        qLen = this.eventQueue.length;
+
+                        for (q = 0; q < qLen; q++) {
+                            queueItemCheck = this.eventQueue[q];
+
+                            if (queueItemCheck) {
+                                queueItemCheckKey = queueItemCheck[0];
+                                queueItemCheckValue = queueItemCheck[1];
+
+                                if (queueItemCheckKey == 
+                                    supercedesCheck.toLowerCase() ) {
+
+                                    this.eventQueue.push([queueItemCheckKey, 
+                                        queueItemCheckValue]);
+
+                                    this.eventQueue[q] = null;
+                                    break;
+
+                                }
+                            }
+                        }
+                    }
+                }
+
+
+                return true;
+            } else {
+                return false;
+            }
+        },
+        
+        /**
+        * Fires the event for a property using the property's current value.
+        * @method refireEvent
+        * @param {String} key The name of the property
+        */
+        refireEvent: function (key) {
+    
+            key = key.toLowerCase();
+        
+            var property = this.config[key];
+    
+            if (property && property.event && 
+    
+                !Lang.isUndefined(property.value)) {
+    
+                if (this.queueInProgress) {
+    
+                    this.queueProperty(key);
+    
+                } else {
+    
+                    this.fireEvent(key, property.value);
+    
+                }
+    
+            }
+        },
+        
+        /**
+        * Applies a key-value Object literal to the configuration, replacing  
+        * any existing values, and queueing the property events.
+        * Although the values will be set, fireQueue() must be called for their 
+        * associated events to execute.
+        * @method applyConfig
+        * @param {Object} userConfig The configuration Object literal
+        * @param {Boolean} init  When set to true, the initialConfig will 
+        * be set to the userConfig passed in, so that calling a reset will 
+        * reset the properties to the passed values.
+        */
+        applyConfig: function (userConfig, init) {
+        
+            var sKey,
+                oConfig;
+
+            if (init) {
+                oConfig = {};
+                for (sKey in userConfig) {
+                    if (Lang.hasOwnProperty(userConfig, sKey)) {
+                        oConfig[sKey.toLowerCase()] = userConfig[sKey];
+                    }
+                }
+                this.initialConfig = oConfig;
+            }
+
+            for (sKey in userConfig) {
+                if (Lang.hasOwnProperty(userConfig, sKey)) {
+                    this.queueProperty(sKey, userConfig[sKey]);
+                }
+            }
+        },
+        
+        /**
+        * Refires the events for all configuration properties using their 
+        * current values.
+        * @method refresh
+        */
+        refresh: function () {
+
+            var prop;
+
+            for (prop in this.config) {
+                if (Lang.hasOwnProperty(this.config, prop)) {
+                    this.refireEvent(prop);
+                }
+            }
+        },
+        
+        /**
+        * Fires the normalized list of queued property change events
+        * @method fireQueue
+        */
+        fireQueue: function () {
+        
+            var i, 
+                queueItem,
+                key,
+                value,
+                property;
+        
+            this.queueInProgress = true;
+            for (i = 0;i < this.eventQueue.length; i++) {
+                queueItem = this.eventQueue[i];
+                if (queueItem) {
+        
+                    key = queueItem[0];
+                    value = queueItem[1];
+                    property = this.config[key];
+
+                    property.value = value;
+
+                    // Clear out queue entry, to avoid it being 
+                    // re-added to the queue by any queueProperty/supercedes
+                    // calls which are invoked during fireEvent
+                    this.eventQueue[i] = null;
+
+                    this.fireEvent(key,value);
+                }
+            }
+            
+            this.queueInProgress = false;
+            this.eventQueue = [];
+        },
+        
+        /**
+        * Subscribes an external handler to the change event for any 
+        * given property. 
+        * @method subscribeToConfigEvent
+        * @param {String} key The property name
+        * @param {Function} handler The handler function to use subscribe to 
+        * the property's event
+        * @param {Object} obj The Object to use for scoping the event handler 
+        * (see CustomEvent documentation)
+        * @param {Boolean} override Optional. If true, will override "this"  
+        * within the handler to map to the scope Object passed into the method.
+        * @return {Boolean} True, if the subscription was successful, 
+        * otherwise false.
+        */ 
+        subscribeToConfigEvent: function (key, handler, obj, override) {
+    
+            var property = this.config[key.toLowerCase()];
+    
+            if (property && property.event) {
+                if (!Config.alreadySubscribed(property.event, handler, obj)) {
+                    property.event.subscribe(handler, obj, override);
+                }
+                return true;
+            } else {
+                return false;
+            }
+    
+        },
+        
+        /**
+        * Unsubscribes an external handler from the change event for any 
+        * given property. 
+        * @method unsubscribeFromConfigEvent
+        * @param {String} key The property name
+        * @param {Function} handler The handler function to use subscribe to 
+        * the property's event
+        * @param {Object} obj The Object to use for scoping the event 
+        * handler (see CustomEvent documentation)
+        * @return {Boolean} True, if the unsubscription was successful, 
+        * otherwise false.
+        */
+        unsubscribeFromConfigEvent: function (key, handler, obj) {
+            var property = this.config[key.toLowerCase()];
+            if (property && property.event) {
+                return property.event.unsubscribe(handler, obj);
+            } else {
+                return false;
+            }
+        },
+        
+        /**
+        * Returns a string representation of the Config object
+        * @method toString
+        * @return {String} The Config object in string format.
+        */
+        toString: function () {
+            var output = "Config";
+            if (this.owner) {
+                output += " [" + this.owner.toString() + "]";
+            }
+            return output;
+        },
+        
+        /**
+        * Returns a string representation of the Config object's current 
+        * CustomEvent queue
+        * @method outputEventQueue
+        * @return {String} The string list of CustomEvents currently queued 
+        * for execution
+        */
+        outputEventQueue: function () {
+
+            var output = "",
+                queueItem,
+                q,
+                nQueue = this.eventQueue.length;
+              
+            for (q = 0; q < nQueue; q++) {
+                queueItem = this.eventQueue[q];
+                if (queueItem) {
+                    output += queueItem[0] + "=" + queueItem[1] + ", ";
+                }
+            }
+            return output;
+        },
+
+        /**
+        * Sets all properties to null, unsubscribes all listeners from each 
+        * property's change event and all listeners from the configChangedEvent.
+        * @method destroy
+        */
+        destroy: function () {
+
+            var oConfig = this.config,
+                sProperty,
+                oProperty;
+
+
+            for (sProperty in oConfig) {
+            
+                if (Lang.hasOwnProperty(oConfig, sProperty)) {
+
+                    oProperty = oConfig[sProperty];
+
+                    oProperty.event.unsubscribeAll();
+                    oProperty.event = null;
+
+                }
+            
+            }
+            
+            this.configChangedEvent.unsubscribeAll();
+            
+            this.configChangedEvent = null;
+            this.owner = null;
+            this.config = null;
+            this.initialConfig = null;
+            this.eventQueue = null;
+        
+        }
+
+    };
+    
+    
+    
+    /**
+    * Checks to determine if a particular function/Object pair are already 
+    * subscribed to the specified CustomEvent
+    * @method YAHOO.util.Config.alreadySubscribed
+    * @static
+    * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check 
+    * the subscriptions
+    * @param {Function} fn The function to look for in the subscribers list
+    * @param {Object} obj The execution scope Object for the subscription
+    * @return {Boolean} true, if the function/Object pair is already subscribed 
+    * to the CustomEvent passed in
+    */
+    Config.alreadySubscribed = function (evt, fn, obj) {
+    
+        var nSubscribers = evt.subscribers.length,
+            subsc,
+            i;
+
+        if (nSubscribers > 0) {
+            i = nSubscribers - 1;
+            do {
+                subsc = evt.subscribers[i];
+                if (subsc && subsc.obj == obj && subsc.fn == fn) {
+                    return true;
+                }
+            }
+            while (i--);
+        }
+
+        return false;
+
+    };
+
+    YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
+
+}());
+
+(function () {
+
+    /**
+    * The Container family of components is designed to enable developers to 
+    * create different kinds of content-containing modules on the web. Module 
+    * and Overlay are the most basic containers, and they can be used directly 
+    * or extended to build custom containers. Also part of the Container family 
+    * are four UI controls that extend Module and Overlay: Tooltip, Panel, 
+    * Dialog, and SimpleDialog.
+    * @module container
+    * @title Container
+    * @requires yahoo, dom, event 
+    * @optional dragdrop, animation, button
+    */
+    
+    /**
+    * Module is a JavaScript representation of the Standard Module Format. 
+    * Standard Module Format is a simple standard for markup containers where 
+    * child nodes representing the header, body, and footer of the content are 
+    * denoted using the CSS classes "hd", "bd", and "ft" respectively. 
+    * Module is the base class for all other classes in the YUI 
+    * Container package.
+    * @namespace YAHOO.widget
+    * @class Module
+    * @constructor
+    * @param {String} el The element ID representing the Module <em>OR</em>
+    * @param {HTMLElement} el The element representing the Module
+    * @param {Object} userConfig The configuration Object literal containing 
+    * the configuration that should be set for this module. See configuration 
+    * documentation for more details.
+    */
+    YAHOO.widget.Module = function (el, userConfig) {
+        if (el) {
+            this.init(el, userConfig);
+        } else {
+        }
+    };
+
+    var Dom = YAHOO.util.Dom,
+        Config = YAHOO.util.Config,
+        Event = YAHOO.util.Event,
+        CustomEvent = YAHOO.util.CustomEvent,
+        Module = YAHOO.widget.Module,
+        UA = YAHOO.env.ua,
+
+        m_oModuleTemplate,
+        m_oHeaderTemplate,
+        m_oBodyTemplate,
+        m_oFooterTemplate,
+
+        /**
+        * Constant representing the name of the Module's events
+        * @property EVENT_TYPES
+        * @private
+        * @final
+        * @type Object
+        */
+        EVENT_TYPES = {
+            "BEFORE_INIT": "beforeInit",
+            "INIT": "init",
+            "APPEND": "append",
+            "BEFORE_RENDER": "beforeRender",
+            "RENDER": "render",
+            "CHANGE_HEADER": "changeHeader",
+            "CHANGE_BODY": "changeBody",
+            "CHANGE_FOOTER": "changeFooter",
+            "CHANGE_CONTENT": "changeContent",
+            "DESTORY": "destroy",
+            "BEFORE_SHOW": "beforeShow",
+            "SHOW": "show",
+            "BEFORE_HIDE": "beforeHide",
+            "HIDE": "hide"
+        },
+            
+        /**
+        * Constant representing the Module's configuration properties
+        * @property DEFAULT_CONFIG
+        * @private
+        * @final
+        * @type Object
+        */
+        DEFAULT_CONFIG = {
+        
+            "VISIBLE": { 
+                key: "visible", 
+                value: true, 
+                validator: YAHOO.lang.isBoolean 
+            },
+
+            "EFFECT": {
+                key: "effect",
+                suppressEvent: true,
+                supercedes: ["visible"]
+            },
+
+            "MONITOR_RESIZE": {
+                key: "monitorresize",
+                value: true
+            },
+
+            "APPEND_TO_DOCUMENT_BODY": {
+                key: "appendtodocumentbody",
+                value: false
+            }
+        };
+
+    /**
+    * Constant representing the prefix path to use for non-secure images
+    * @property YAHOO.widget.Module.IMG_ROOT
+    * @static
+    * @final
+    * @type String
+    */
+    Module.IMG_ROOT = null;
+    
+    /**
+    * Constant representing the prefix path to use for securely served images
+    * @property YAHOO.widget.Module.IMG_ROOT_SSL
+    * @static
+    * @final
+    * @type String
+    */
+    Module.IMG_ROOT_SSL = null;
+    
+    /**
+    * Constant for the default CSS class name that represents a Module
+    * @property YAHOO.widget.Module.CSS_MODULE
+    * @static
+    * @final
+    * @type String
+    */
+    Module.CSS_MODULE = "yui-module";
+    
+    /**
+    * Constant representing the module header
+    * @property YAHOO.widget.Module.CSS_HEADER
+    * @static
+    * @final
+    * @type String
+    */
+    Module.CSS_HEADER = "hd";
+
+    /**
+    * Constant representing the module body
+    * @property YAHOO.widget.Module.CSS_BODY
+    * @static
+    * @final
+    * @type String
+    */
+    Module.CSS_BODY = "bd";
+    
+    /**
+    * Constant representing the module footer
+    * @property YAHOO.widget.Module.CSS_FOOTER
+    * @static
+    * @final
+    * @type String
+    */
+    Module.CSS_FOOTER = "ft";
+    
+    /**
+    * Constant representing the url for the "src" attribute of the iframe 
+    * used to monitor changes to the browser's base font size
+    * @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
+    * @static
+    * @final
+    * @type String
+    */
+    Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
+
+    /**
+    * Constant representing the buffer amount (in pixels) to use when positioning
+    * the text resize monitor offscreen. The resize monitor is positioned
+    * offscreen by an amount eqaul to its offsetHeight + the buffer value.
+    * 
+    * @property YAHOO.widget.Module.RESIZE_MONITOR_BUFFER
+    * @static
+    * @type Number
+    */
+    // Set to 1, to work around pixel offset in IE8, which increases when zoom is used
+    Module.RESIZE_MONITOR_BUFFER = 1;
+
+    /**
+    * Singleton CustomEvent fired when the font size is changed in the browser.
+    * Opera's "zoom" functionality currently does not support text 
+    * size detection.
+    * @event YAHOO.widget.Module.textResizeEvent
+    */
+    Module.textResizeEvent = new CustomEvent("textResize");
+
+    /**
+     * Helper utility method, which forces a document level 
+     * redraw for Opera, which can help remove repaint
+     * irregularities after applying DOM changes.
+     *
+     * @method YAHOO.widget.Module.forceDocumentRedraw
+     * @static
+     */
+    Module.forceDocumentRedraw = function() {
+        var docEl = document.documentElement;
+        if (docEl) {
+            docEl.className += " ";
+            docEl.className = YAHOO.lang.trim(docEl.className);
+        }
+    };
+
+    function createModuleTemplate() {
+
+        if (!m_oModuleTemplate) {
+            m_oModuleTemplate = document.createElement("div");
+            
+            m_oModuleTemplate.innerHTML = ("<div class=\"" + 
+                Module.CSS_HEADER + "\"></div>" + "<div class=\"" + 
+                Module.CSS_BODY + "\"></div><div class=\"" + 
+                Module.CSS_FOOTER + "\"></div>");
+
+            m_oHeaderTemplate = m_oModuleTemplate.firstChild;
+            m_oBodyTemplate = m_oHeaderTemplate.nextSibling;
+            m_oFooterTemplate = m_oBodyTemplate.nextSibling;
+        }
+
+        return m_oModuleTemplate;
+    }
+
+    function createHeader() {
+        if (!m_oHeaderTemplate) {
+            createModuleTemplate();
+        }
+        return (m_oHeaderTemplate.cloneNode(false));
+    }
+
+    function createBody() {
+        if (!m_oBodyTemplate) {
+            createModuleTemplate();
+        }
+        return (m_oBodyTemplate.cloneNode(false));
+    }
+
+    function createFooter() {
+        if (!m_oFooterTemplate) {
+            createModuleTemplate();
+        }
+        return (m_oFooterTemplate.cloneNode(false));
+    }
+
+    Module.prototype = {
+
+        /**
+        * The class's constructor function
+        * @property contructor
+        * @type Function
+        */
+        constructor: Module,
+        
+        /**
+        * The main module element that contains the header, body, and footer
+        * @property element
+        * @type HTMLElement
+        */
+        element: null,
+
+        /**
+        * The header element, denoted with CSS class "hd"
+        * @property header
+        * @type HTMLElement
+        */
+        header: null,
+
+        /**
+        * The body element, denoted with CSS class "bd"
+        * @property body
+        * @type HTMLElement
+        */
+        body: null,
+
+        /**
+        * The footer element, denoted with CSS class "ft"
+        * @property footer
+        * @type HTMLElement
+        */
+        footer: null,
+
+        /**
+        * The id of the element
+        * @property id
+        * @type String
+        */
+        id: null,
+
+        /**
+        * A string representing the root path for all images created by
+        * a Module instance.
+        * @deprecated It is recommend that any images for a Module be applied
+        * via CSS using the "background-image" property.
+        * @property imageRoot
+        * @type String
+        */
+        imageRoot: Module.IMG_ROOT,
+
+        /**
+        * Initializes the custom events for Module which are fired 
+        * automatically at appropriate times by the Module class.
+        * @method initEvents
+        */
+        initEvents: function () {
+
+            var SIGNATURE = CustomEvent.LIST;
+
+            /**
+            * CustomEvent fired prior to class initalization.
+            * @event beforeInitEvent
+            * @param {class} classRef class reference of the initializing 
+            * class, such as this.beforeInitEvent.fire(Module)
+            */
+            this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT);
+            this.beforeInitEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired after class initalization.
+            * @event initEvent
+            * @param {class} classRef class reference of the initializing 
+            * class, such as this.beforeInitEvent.fire(Module)
+            */  
+            this.initEvent = this.createEvent(EVENT_TYPES.INIT);
+            this.initEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired when the Module is appended to the DOM
+            * @event appendEvent
+            */
+            this.appendEvent = this.createEvent(EVENT_TYPES.APPEND);
+            this.appendEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired before the Module is rendered
+            * @event beforeRenderEvent
+            */
+            this.beforeRenderEvent = this.createEvent(EVENT_TYPES.BEFORE_RENDER);
+            this.beforeRenderEvent.signature = SIGNATURE;
+        
+            /**
+            * CustomEvent fired after the Module is rendered
+            * @event renderEvent
+            */
+            this.renderEvent = this.createEvent(EVENT_TYPES.RENDER);
+            this.renderEvent.signature = SIGNATURE;
+        
+            /**
+            * CustomEvent fired when the header content of the Module 
+            * is modified
+            * @event changeHeaderEvent
+            * @param {String/HTMLElement} content String/element representing 
+            * the new header content
+            */
+            this.changeHeaderEvent = this.createEvent(EVENT_TYPES.CHANGE_HEADER);
+            this.changeHeaderEvent.signature = SIGNATURE;
+            
+            /**
+            * CustomEvent fired when the body content of the Module is modified
+            * @event changeBodyEvent
+            * @param {String/HTMLElement} content String/element representing 
+            * the new body content
+            */  
+            this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY);
+            this.changeBodyEvent.signature = SIGNATURE;
+            
+            /**
+            * CustomEvent fired when the footer content of the Module 
+            * is modified
+            * @event changeFooterEvent
+            * @param {String/HTMLElement} content String/element representing 
+            * the new footer content
+            */
+            this.changeFooterEvent = this.createEvent(EVENT_TYPES.CHANGE_FOOTER);
+            this.changeFooterEvent.signature = SIGNATURE;
+        
+            /**
+            * CustomEvent fired when the content of the Module is modified
+            * @event changeContentEvent
+            */
+            this.changeContentEvent = this.createEvent(EVENT_TYPES.CHANGE_CONTENT);
+            this.changeContentEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired when the Module is destroyed
+            * @event destroyEvent
+            */
+            this.destroyEvent = this.createEvent(EVENT_TYPES.DESTORY);
+            this.destroyEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired before the Module is shown
+            * @event beforeShowEvent
+            */
+            this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW);
+            this.beforeShowEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired after the Module is shown
+            * @event showEvent
+            */
+            this.showEvent = this.createEvent(EVENT_TYPES.SHOW);
+            this.showEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired before the Module is hidden
+            * @event beforeHideEvent
+            */
+            this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE);
+            this.beforeHideEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired after the Module is hidden
+            * @event hideEvent
+            */
+            this.hideEvent = this.createEvent(EVENT_TYPES.HIDE);
+            this.hideEvent.signature = SIGNATURE;
+        }, 
+
+        /**
+        * String representing the current user-agent platform
+        * @property platform
+        * @type String
+        */
+        platform: function () {
+            var ua = navigator.userAgent.toLowerCase();
+
+            if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
+                return "windows";
+            } else if (ua.indexOf("macintosh") != -1) {
+                return "mac";
+            } else {
+                return false;
+            }
+        }(),
+        
+        /**
+        * String representing the user-agent of the browser
+        * @deprecated Use YAHOO.env.ua
+        * @property browser
+        * @type String
+        */
+        browser: function () {
+            var ua = navigator.userAgent.toLowerCase();
+            /*
+                 Check Opera first in case of spoof and check Safari before
+                 Gecko since Safari's user agent string includes "like Gecko"
+            */
+            if (ua.indexOf('opera') != -1) { 
+                return 'opera';
+            } else if (ua.indexOf('msie 7') != -1) {
+                return 'ie7';
+            } else if (ua.indexOf('msie') != -1) {
+                return 'ie';
+            } else if (ua.indexOf('safari') != -1) { 
+                return 'safari';
+            } else if (ua.indexOf('gecko') != -1) {
+                return 'gecko';
+            } else {
+                return false;
+            }
+        }(),
+        
+        /**
+        * Boolean representing whether or not the current browsing context is 
+        * secure (https)
+        * @property isSecure
+        * @type Boolean
+        */
+        isSecure: function () {
+            if (window.location.href.toLowerCase().indexOf("https") === 0) {
+                return true;
+            } else {
+                return false;
+            }
+        }(),
+        
+        /**
+        * Initializes the custom events for Module which are fired 
+        * automatically at appropriate times by the Module class.
+        */
+        initDefaultConfig: function () {
+            // Add properties //
+            /**
+            * Specifies whether the Module is visible on the page.
+            * @config visible
+            * @type Boolean
+            * @default true
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, {
+                handler: this.configVisible, 
+                value: DEFAULT_CONFIG.VISIBLE.value, 
+                validator: DEFAULT_CONFIG.VISIBLE.validator
+            });
+
+            /**
+            * <p>
+            * Object or array of objects representing the ContainerEffect 
+            * classes that are active for animating the container.
+            * </p>
+            * <p>
+            * <strong>NOTE:</strong> Although this configuration 
+            * property is introduced at the Module level, an out of the box
+            * implementation is not shipped for the Module class so setting
+            * the proroperty on the Module class has no effect. The Overlay 
+            * class is the first class to provide out of the box ContainerEffect 
+            * support.
+            * </p>
+            * @config effect
+            * @type Object
+            * @default null
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, {
+                suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent, 
+                supercedes: DEFAULT_CONFIG.EFFECT.supercedes
+            });
+
+            /**
+            * Specifies whether to create a special proxy iframe to monitor 
+            * for user font resizing in the document
+            * @config monitorresize
+            * @type Boolean
+            * @default true
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, {
+                handler: this.configMonitorResize,
+                value: DEFAULT_CONFIG.MONITOR_RESIZE.value
+            });
+
+            /**
+            * Specifies if the module should be rendered as the first child 
+            * of document.body or appended as the last child when render is called
+            * with document.body as the "appendToNode".
+            * <p>
+            * Appending to the body while the DOM is still being constructed can 
+            * lead to Operation Aborted errors in IE hence this flag is set to 
+            * false by default.
+            * </p>
+            * 
+            * @config appendtodocumentbody
+            * @type Boolean
+            * @default false
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.key, {
+                value: DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.value
+            });
+        },
+
+        /**
+        * The Module class's initialization method, which is executed for
+        * Module and all of its subclasses. This method is automatically 
+        * called by the constructor, and  sets up all DOM references for 
+        * pre-existing markup, and creates required markup if it is not 
+        * already present.
+        * <p>
+        * If the element passed in does not have an id, one will be generated
+        * for it.
+        * </p>
+        * @method init
+        * @param {String} el The element ID representing the Module <em>OR</em>
+        * @param {HTMLElement} el The element representing the Module
+        * @param {Object} userConfig The configuration Object literal 
+        * containing the configuration that should be set for this module. 
+        * See configuration documentation for more details.
+        */
+        init: function (el, userConfig) {
+
+            var elId, child;
+
+            this.initEvents();
+            this.beforeInitEvent.fire(Module);
+
+            /**
+            * The Module's Config object used for monitoring 
+            * configuration properties.
+            * @property cfg
+            * @type YAHOO.util.Config
+            */
+            this.cfg = new Config(this);
+
+            if (this.isSecure) {
+                this.imageRoot = Module.IMG_ROOT_SSL;
+            }
+
+            if (typeof el == "string") {
+                elId = el;
+                el = document.getElementById(el);
+                if (! el) {
+                    el = (createModuleTemplate()).cloneNode(false);
+                    el.id = elId;
+                }
+            }
+
+            this.id = Dom.generateId(el);
+            this.element = el;
+
+            child = this.element.firstChild;
+
+            if (child) {
+                var fndHd = false, fndBd = false, fndFt = false;
+                do {
+                    // We're looking for elements
+                    if (1 == child.nodeType) {
+                        if (!fndHd && Dom.hasClass(child, Module.CSS_HEADER)) {
+                            this.header = child;
+                            fndHd = true;
+                        } else if (!fndBd && Dom.hasClass(child, Module.CSS_BODY)) {
+                            this.body = child;
+                            fndBd = true;
+                        } else if (!fndFt && Dom.hasClass(child, Module.CSS_FOOTER)){
+                            this.footer = child;
+                            fndFt = true;
+                        }
+                    }
+                } while ((child = child.nextSibling));
+            }
+
+            this.initDefaultConfig();
+
+            Dom.addClass(this.element, Module.CSS_MODULE);
+
+            if (userConfig) {
+                this.cfg.applyConfig(userConfig, true);
+            }
+
+            /*
+                Subscribe to the fireQueue() method of Config so that any 
+                queued configuration changes are excecuted upon render of 
+                the Module
+            */ 
+
+            if (!Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) {
+                this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
+            }
+
+            this.initEvent.fire(Module);
+        },
+
+        /**
+        * Initialize an empty IFRAME that is placed out of the visible area 
+        * that can be used to detect text resize.
+        * @method initResizeMonitor
+        */
+        initResizeMonitor: function () {
+
+            var isGeckoWin = (UA.gecko && this.platform == "windows");
+            if (isGeckoWin) {
+                // Help prevent spinning loading icon which 
+                // started with FireFox 2.0.0.8/Win
+                var self = this;
+                setTimeout(function(){self._initResizeMonitor();}, 0);
+            } else {
+                this._initResizeMonitor();
+            }
+        },
+
+        /**
+         * Create and initialize the text resize monitoring iframe.
+         * 
+         * @protected
+         * @method _initResizeMonitor
+         */
+        _initResizeMonitor : function() {
+
+            var oDoc, 
+                oIFrame, 
+                sHTML;
+
+            function fireTextResize() {
+                Module.textResizeEvent.fire();
+            }
+
+            if (!UA.opera) {
+                oIFrame = Dom.get("_yuiResizeMonitor");
+
+                var supportsCWResize = this._supportsCWResize();
+
+                if (!oIFrame) {
+                    oIFrame = document.createElement("iframe");
+
+                    if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && UA.ie) {
+                        oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL;
+                    }
+
+                    if (!supportsCWResize) {
+                        // Can't monitor on contentWindow, so fire from inside iframe
+                        sHTML = ["<html><head><script ",
+                                 "type=\"text/javascript\">",
+                                 "window.onresize=function(){window.parent.",
+                                 "YAHOO.widget.Module.textResizeEvent.",
+                                 "fire();};<",
+                                 "\/script></head>",
+                                 "<body></body></html>"].join('');
+
+                        oIFrame.src = "data:text/html;charset=utf-8," + encodeURIComponent(sHTML);
+                    }
+
+                    oIFrame.id = "_yuiResizeMonitor";
+                    oIFrame.title = "Text Resize Monitor";
+                    /*
+                        Need to set "position" property before inserting the 
+                        iframe into the document or Safari's status bar will 
+                        forever indicate the iframe is loading 
+                        (See SourceForge bug #1723064)
+                    */
+                    oIFrame.style.position = "absolute";
+                    oIFrame.style.visibility = "hidden";
+
+                    var db = document.body,
+                        fc = db.firstChild;
+                    if (fc) {
+                        db.insertBefore(oIFrame, fc);
+                    } else {
+                        db.appendChild(oIFrame);
+                    }
+
+                    oIFrame.style.width = "2em";
+                    oIFrame.style.height = "2em";
+                    oIFrame.style.top = (-1 * (oIFrame.offsetHeight + Module.RESIZE_MONITOR_BUFFER)) + "px";
+                    oIFrame.style.left = "0";
+                    oIFrame.style.borderWidth = "0";
+                    oIFrame.style.visibility = "visible";
+
+                    /*
+                       Don't open/close the document for Gecko like we used to, since it
+                       leads to duplicate cookies. (See SourceForge bug #1721755)
+                    */
+                    if (UA.webkit) {
+                        oDoc = oIFrame.contentWindow.document;
+                        oDoc.open();
+                        oDoc.close();
+                    }
+                }
+
+                if (oIFrame && oIFrame.contentWindow) {
+                    Module.textResizeEvent.subscribe(this.onDomResize, this, true);
+
+                    if (!Module.textResizeInitialized) {
+                        if (supportsCWResize) {
+                            if (!Event.on(oIFrame.contentWindow, "resize", fireTextResize)) {
+                                /*
+                                     This will fail in IE if document.domain has 
+                                     changed, so we must change the listener to 
+                                     use the oIFrame element instead
+                                */
+                                Event.on(oIFrame, "resize", fireTextResize);
+                            }
+                        }
+                        Module.textResizeInitialized = true;
+                    }
+                    this.resizeMonitor = oIFrame;
+                }
+            }
+        },
+
+        /**
+         * Text resize monitor helper method.
+         * Determines if the browser supports resize events on iframe content windows.
+         * 
+         * @private
+         * @method _supportsCWResize
+         */
+        _supportsCWResize : function() {
+            /*
+                Gecko 1.8.0 (FF1.5), 1.8.1.0-5 (FF2) won't fire resize on contentWindow.
+                Gecko 1.8.1.6+ (FF2.0.0.6+) and all other browsers will fire resize on contentWindow.
+
+                We don't want to start sniffing for patch versions, so fire textResize the same
+                way on all FF2 flavors
+             */
+            var bSupported = true;
+            if (UA.gecko && UA.gecko <= 1.8) {
+                bSupported = false;
+            }
+            return bSupported;
+        },
+
+        /**
+        * Event handler fired when the resize monitor element is resized.
+        * @method onDomResize
+        * @param {DOMEvent} e The DOM resize event
+        * @param {Object} obj The scope object passed to the handler
+        */
+        onDomResize: function (e, obj) {
+
+            var nTop = -1 * (this.resizeMonitor.offsetHeight + Module.RESIZE_MONITOR_BUFFER);
+
+            this.resizeMonitor.style.top = nTop + "px";
+            this.resizeMonitor.style.left = "0";
+        },
+
+        /**
+        * Sets the Module's header content to the string specified, or appends 
+        * the passed element to the header. If no header is present, one will 
+        * be automatically created. An empty string can be passed to the method
+        * to clear the contents of the header.
+        * 
+        * @method setHeader
+        * @param {String} headerContent The string used to set the header.
+        * As a convenience, non HTMLElement objects can also be passed into 
+        * the method, and will be treated as strings, with the header innerHTML
+        * set to their default toString implementations.
+        * <em>OR</em>
+        * @param {HTMLElement} headerContent The HTMLElement to append to 
+        * <em>OR</em>
+        * @param {DocumentFragment} headerContent The document fragment 
+        * containing elements which are to be added to the header
+        */
+        setHeader: function (headerContent) {
+            var oHeader = this.header || (this.header = createHeader());
+
+            if (headerContent.nodeName) {
+                oHeader.innerHTML = "";
+                oHeader.appendChild(headerContent);
+            } else {
+                oHeader.innerHTML = headerContent;
+            }
+
+            this.changeHeaderEvent.fire(headerContent);
+            this.changeContentEvent.fire();
+
+        },
+
+        /**
+        * Appends the passed element to the header. If no header is present, 
+        * one will be automatically created.
+        * @method appendToHeader
+        * @param {HTMLElement | DocumentFragment} element The element to 
+        * append to the header. In the case of a document fragment, the
+        * children of the fragment will be appended to the header.
+        */
+        appendToHeader: function (element) {
+            var oHeader = this.header || (this.header = createHeader());
+
+            oHeader.appendChild(element);
+
+            this.changeHeaderEvent.fire(element);
+            this.changeContentEvent.fire();
+
+        },
+
+        /**
+        * Sets the Module's body content to the HTML specified. 
+        * 
+        * If no body is present, one will be automatically created. 
+        * 
+        * An empty string can be passed to the method to clear the contents of the body.
+        * @method setBody
+        * @param {String} bodyContent The HTML used to set the body. 
+        * As a convenience, non HTMLElement objects can also be passed into 
+        * the method, and will be treated as strings, with the body innerHTML
+        * set to their default toString implementations.
+        * <em>OR</em>
+        * @param {HTMLElement} bodyContent The HTMLElement to add as the first and only
+        * child of the body element.
+        * <em>OR</em>
+        * @param {DocumentFragment} bodyContent The document fragment 
+        * containing elements which are to be added to the body
+        */
+        setBody: function (bodyContent) {
+            var oBody = this.body || (this.body = createBody());
+
+            if (bodyContent.nodeName) {
+                oBody.innerHTML = "";
+                oBody.appendChild(bodyContent);
+            } else {
+                oBody.innerHTML = bodyContent;
+            }
+
+            this.changeBodyEvent.fire(bodyContent);
+            this.changeContentEvent.fire();
+        },
+
+        /**
+        * Appends the passed element to the body. If no body is present, one 
+        * will be automatically created.
+        * @method appendToBody
+        * @param {HTMLElement | DocumentFragment} element The element to 
+        * append to the body. In the case of a document fragment, the
+        * children of the fragment will be appended to the body.
+        * 
+        */
+        appendToBody: function (element) {
+            var oBody = this.body || (this.body = createBody());
+        
+            oBody.appendChild(element);
+
+            this.changeBodyEvent.fire(element);
+            this.changeContentEvent.fire();
+
+        },
+        
+        /**
+        * Sets the Module's footer content to the HTML specified, or appends 
+        * the passed element to the footer. If no footer is present, one will 
+        * be automatically created. An empty string can be passed to the method
+        * to clear the contents of the footer.
+        * @method setFooter
+        * @param {String} footerContent The HTML used to set the footer 
+        * As a convenience, non HTMLElement objects can also be passed into 
+        * the method, and will be treated as strings, with the footer innerHTML
+        * set to their default toString implementations.
+        * <em>OR</em>
+        * @param {HTMLElement} footerContent The HTMLElement to append to 
+        * the footer
+        * <em>OR</em>
+        * @param {DocumentFragment} footerContent The document fragment containing 
+        * elements which are to be added to the footer
+        */
+        setFooter: function (footerContent) {
+
+            var oFooter = this.footer || (this.footer = createFooter());
+
+            if (footerContent.nodeName) {
+                oFooter.innerHTML = "";
+                oFooter.appendChild(footerContent);
+            } else {
+                oFooter.innerHTML = footerContent;
+            }
+
+            this.changeFooterEvent.fire(footerContent);
+            this.changeContentEvent.fire();
+        },
+
+        /**
+        * Appends the passed element to the footer. If no footer is present, 
+        * one will be automatically created.
+        * @method appendToFooter
+        * @param {HTMLElement | DocumentFragment} element The element to 
+        * append to the footer. In the case of a document fragment, the
+        * children of the fragment will be appended to the footer
+        */
+        appendToFooter: function (element) {
+
+            var oFooter = this.footer || (this.footer = createFooter());
+
+            oFooter.appendChild(element);
+
+            this.changeFooterEvent.fire(element);
+            this.changeContentEvent.fire();
+
+        },
+
+        /**
+        * Renders the Module by inserting the elements that are not already 
+        * in the main Module into their correct places. Optionally appends 
+        * the Module to the specified node prior to the render's execution. 
+        * <p>
+        * For Modules without existing markup, the appendToNode argument 
+        * is REQUIRED. If this argument is ommitted and the current element is 
+        * not present in the document, the function will return false, 
+        * indicating that the render was a failure.
+        * </p>
+        * <p>
+        * NOTE: As of 2.3.1, if the appendToNode is the document's body element
+        * then the module is rendered as the first child of the body element, 
+        * and not appended to it, to avoid Operation Aborted errors in IE when 
+        * rendering the module before window's load event is fired. You can 
+        * use the appendtodocumentbody configuration property to change this 
+        * to append to document.body if required.
+        * </p>
+        * @method render
+        * @param {String} appendToNode The element id to which the Module 
+        * should be appended to prior to rendering <em>OR</em>
+        * @param {HTMLElement} appendToNode The element to which the Module 
+        * should be appended to prior to rendering
+        * @param {HTMLElement} moduleElement OPTIONAL. The element that 
+        * represents the actual Standard Module container.
+        * @return {Boolean} Success or failure of the render
+        */
+        render: function (appendToNode, moduleElement) {
+
+            var me = this,
+                firstChild;
+
+            function appendTo(parentNode) {
+                if (typeof parentNode == "string") {
+                    parentNode = document.getElementById(parentNode);
+                }
+
+                if (parentNode) {
+                    me._addToParent(parentNode, me.element);
+                    me.appendEvent.fire();
+                }
+            }
+
+            this.beforeRenderEvent.fire();
+
+            if (! moduleElement) {
+                moduleElement = this.element;
+            }
+
+            if (appendToNode) {
+                appendTo(appendToNode);
+            } else { 
+                // No node was passed in. If the element is not already in the Dom, this fails
+                if (! Dom.inDocument(this.element)) {
+                    return false;
+                }
+            }
+
+            // Need to get everything into the DOM if it isn't already
+            if (this.header && ! Dom.inDocument(this.header)) {
+                // There is a header, but it's not in the DOM yet. Need to add it.
+                firstChild = moduleElement.firstChild;
+                if (firstChild) {
+                    moduleElement.insertBefore(this.header, firstChild);
+                } else {
+                    moduleElement.appendChild(this.header);
+                }
+            }
+
+            if (this.body && ! Dom.inDocument(this.body)) {
+                // There is a body, but it's not in the DOM yet. Need to add it.               
+                if (this.footer && Dom.isAncestor(this.moduleElement, this.footer)) {
+                    moduleElement.insertBefore(this.body, this.footer);
+                } else {
+                    moduleElement.appendChild(this.body);
+                }
+            }
+
+            if (this.footer && ! Dom.inDocument(this.footer)) {
+                // There is a footer, but it's not in the DOM yet. Need to add it.
+                moduleElement.appendChild(this.footer);
+            }
+
+            this.renderEvent.fire();
+            return true;
+        },
+
+        /**
+        * Removes the Module element from the DOM and sets all child elements 
+        * to null.
+        * @method destroy
+        */
+        destroy: function () {
+
+            var parent;
+
+            if (this.element) {
+                Event.purgeElement(this.element, true);
+                parent = this.element.parentNode;
+            }
+
+            if (parent) {
+                parent.removeChild(this.element);
+            }
+        
+            this.element = null;
+            this.header = null;
+            this.body = null;
+            this.footer = null;
+
+            Module.textResizeEvent.unsubscribe(this.onDomResize, this);
+
+            this.cfg.destroy();
+            this.cfg = null;
+
+            this.destroyEvent.fire();
+        },
+
+        /**
+        * Shows the Module element by setting the visible configuration 
+        * property to true. Also fires two events: beforeShowEvent prior to 
+        * the visibility change, and showEvent after.
+        * @method show
+        */
+        show: function () {
+            this.cfg.setProperty("visible", true);
+        },
+
+        /**
+        * Hides the Module element by setting the visible configuration 
+        * property to false. Also fires two events: beforeHideEvent prior to 
+        * the visibility change, and hideEvent after.
+        * @method hide
+        */
+        hide: function () {
+            this.cfg.setProperty("visible", false);
+        },
+        
+        // BUILT-IN EVENT HANDLERS FOR MODULE //
+        /**
+        * Default event handler for changing the visibility property of a 
+        * Module. By default, this is achieved by switching the "display" style 
+        * between "block" and "none".
+        * This method is responsible for firing showEvent and hideEvent.
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        * @method configVisible
+        */
+        configVisible: function (type, args, obj) {
+            var visible = args[0];
+            if (visible) {
+                this.beforeShowEvent.fire();
+                Dom.setStyle(this.element, "display", "block");
+                this.showEvent.fire();
+            } else {
+                this.beforeHideEvent.fire();
+                Dom.setStyle(this.element, "display", "none");
+                this.hideEvent.fire();
+            }
+        },
+
+        /**
+        * Default event handler for the "monitorresize" configuration property
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        * @method configMonitorResize
+        */
+        configMonitorResize: function (type, args, obj) {
+            var monitor = args[0];
+            if (monitor) {
+                this.initResizeMonitor();
+            } else {
+                Module.textResizeEvent.unsubscribe(this.onDomResize, this, true);
+                this.resizeMonitor = null;
+            }
+        },
+
+        /**
+         * This method is a protected helper, used when constructing the DOM structure for the module 
+         * to account for situations which may cause Operation Aborted errors in IE. It should not 
+         * be used for general DOM construction.
+         * <p>
+         * If the parentNode is not document.body, the element is appended as the last element.
+         * </p>
+         * <p>
+         * If the parentNode is document.body the element is added as the first child to help
+         * prevent Operation Aborted errors in IE.
+         * </p>
+         *
+         * @param {parentNode} The HTML element to which the element will be added
+         * @param {element} The HTML element to be added to parentNode's children
+         * @method _addToParent
+         * @protected
+         */
+        _addToParent: function(parentNode, element) {
+            if (!this.cfg.getProperty("appendtodocumentbody") && parentNode === document.body && parentNode.firstChild) {
+                parentNode.insertBefore(element, parentNode.firstChild);
+            } else {
+                parentNode.appendChild(element);
+            }
+        },
+
+        /**
+        * Returns a String representation of the Object.
+        * @method toString
+        * @return {String} The string representation of the Module
+        */
+        toString: function () {
+            return "Module " + this.id;
+        }
+    };
+
+    YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
+
+}());
+
+(function () {
+
+    /**
+    * Overlay is a Module that is absolutely positioned above the page flow. It 
+    * has convenience methods for positioning and sizing, as well as options for 
+    * controlling zIndex and constraining the Overlay's position to the current 
+    * visible viewport. Overlay also contains a dynamicly generated IFRAME which 
+    * is placed beneath it for Internet Explorer 6 and 5.x so that it will be 
+    * properly rendered above SELECT elements.
+    * @namespace YAHOO.widget
+    * @class Overlay
+    * @extends YAHOO.widget.Module
+    * @param {String} el The element ID representing the Overlay <em>OR</em>
+    * @param {HTMLElement} el The element representing the Overlay
+    * @param {Object} userConfig The configuration object literal containing 
+    * the configuration that should be set for this Overlay. See configuration 
+    * documentation for more details.
+    * @constructor
+    */
+    YAHOO.widget.Overlay = function (el, userConfig) {
+        YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
+    };
+
+    var Lang = YAHOO.lang,
+        CustomEvent = YAHOO.util.CustomEvent,
+        Module = YAHOO.widget.Module,
+        Event = YAHOO.util.Event,
+        Dom = YAHOO.util.Dom,
+        Config = YAHOO.util.Config,
+        UA = YAHOO.env.ua,
+        Overlay = YAHOO.widget.Overlay,
+
+        _SUBSCRIBE = "subscribe",
+        _UNSUBSCRIBE = "unsubscribe",
+        _CONTAINED = "contained",
+
+        m_oIFrameTemplate,
+
+        /**
+        * Constant representing the name of the Overlay's events
+        * @property EVENT_TYPES
+        * @private
+        * @final
+        * @type Object
+        */
+        EVENT_TYPES = {
+            "BEFORE_MOVE": "beforeMove",
+            "MOVE": "move"
+        },
+
+        /**
+        * Constant representing the Overlay's configuration properties
+        * @property DEFAULT_CONFIG
+        * @private
+        * @final
+        * @type Object
+        */
+        DEFAULT_CONFIG = {
+
+            "X": { 
+                key: "x", 
+                validator: Lang.isNumber, 
+                suppressEvent: true, 
+                supercedes: ["iframe"]
+            },
+
+            "Y": { 
+                key: "y", 
+                validator: Lang.isNumber, 
+                suppressEvent: true, 
+                supercedes: ["iframe"]
+            },
+
+            "XY": { 
+                key: "xy", 
+                suppressEvent: true, 
+                supercedes: ["iframe"] 
+            },
+
+            "CONTEXT": { 
+                key: "context", 
+                suppressEvent: true, 
+                supercedes: ["iframe"] 
+            },
+
+            "FIXED_CENTER": { 
+                key: "fixedcenter", 
+                value: false, 
+                supercedes: ["iframe", "visible"] 
+            },
+
+            "WIDTH": { 
+                key: "width",
+                suppressEvent: true,
+                supercedes: ["context", "fixedcenter", "iframe"]
+            }, 
+
+            "HEIGHT": { 
+                key: "height", 
+                suppressEvent: true, 
+                supercedes: ["context", "fixedcenter", "iframe"] 
+            },
+
+            "AUTO_FILL_HEIGHT" : {
+                key: "autofillheight",
+                supercedes: ["height"],
+                value:"body"
+            },
+
+            "ZINDEX": { 
+                key: "zindex", 
+                value: null 
+            },
+
+            "CONSTRAIN_TO_VIEWPORT": { 
+                key: "constraintoviewport", 
+                value: false, 
+                validator: Lang.isBoolean, 
+                supercedes: ["iframe", "x", "y", "xy"]
+            }, 
+
+            "IFRAME": { 
+                key: "iframe", 
+                value: (UA.ie == 6 ? true : false), 
+                validator: Lang.isBoolean, 
+                supercedes: ["zindex"] 
+            },
+
+            "PREVENT_CONTEXT_OVERLAP": {
+                key: "preventcontextoverlap",
+                value: false,
+                validator: Lang.isBoolean,  
+                supercedes: ["constraintoviewport"]
+            }
+
+        };
+
+    /**
+    * The URL that will be placed in the iframe
+    * @property YAHOO.widget.Overlay.IFRAME_SRC
+    * @static
+    * @final
+    * @type String
+    */
+    Overlay.IFRAME_SRC = "javascript:false;";
+
+    /**
+    * Number representing how much the iframe shim should be offset from each 
+    * side of an Overlay instance, in pixels.
+    * @property YAHOO.widget.Overlay.IFRAME_SRC
+    * @default 3
+    * @static
+    * @final
+    * @type Number
+    */
+    Overlay.IFRAME_OFFSET = 3;
+
+    /**
+    * Number representing the minimum distance an Overlay instance should be 
+    * positioned relative to the boundaries of the browser's viewport, in pixels.
+    * @property YAHOO.widget.Overlay.VIEWPORT_OFFSET
+    * @default 10
+    * @static
+    * @final
+    * @type Number
+    */
+    Overlay.VIEWPORT_OFFSET = 10;
+
+    /**
+    * Constant representing the top left corner of an element, used for 
+    * configuring the context element alignment
+    * @property YAHOO.widget.Overlay.TOP_LEFT
+    * @static
+    * @final
+    * @type String
+    */
+    Overlay.TOP_LEFT = "tl";
+
+    /**
+    * Constant representing the top right corner of an element, used for 
+    * configuring the context element alignment
+    * @property YAHOO.widget.Overlay.TOP_RIGHT
+    * @static
+    * @final
+    * @type String
+    */
+    Overlay.TOP_RIGHT = "tr";
+
+    /**
+    * Constant representing the top bottom left corner of an element, used for 
+    * configuring the context element alignment
+    * @property YAHOO.widget.Overlay.BOTTOM_LEFT
+    * @static
+    * @final
+    * @type String
+    */
+    Overlay.BOTTOM_LEFT = "bl";
+
+    /**
+    * Constant representing the bottom right corner of an element, used for 
+    * configuring the context element alignment
+    * @property YAHOO.widget.Overlay.BOTTOM_RIGHT
+    * @static
+    * @final
+    * @type String
+    */
+    Overlay.BOTTOM_RIGHT = "br";
+
+    /**
+    * Constant representing the default CSS class used for an Overlay
+    * @property YAHOO.widget.Overlay.CSS_OVERLAY
+    * @static
+    * @final
+    * @type String
+    */
+    Overlay.CSS_OVERLAY = "yui-overlay";
+
+    /**
+     * Constant representing the names of the standard module elements
+     * used in the overlay.
+     * @property YAHOO.widget.Overlay.STD_MOD_RE
+     * @static
+     * @final
+     * @type RegExp
+     */
+    Overlay.STD_MOD_RE = /^\s*?(body|footer|header)\s*?$/i;
+
+    /**
+    * A singleton CustomEvent used for reacting to the DOM event for 
+    * window scroll
+    * @event YAHOO.widget.Overlay.windowScrollEvent
+    */
+    Overlay.windowScrollEvent = new CustomEvent("windowScroll");
+
+    /**
+    * A singleton CustomEvent used for reacting to the DOM event for
+    * window resize
+    * @event YAHOO.widget.Overlay.windowResizeEvent
+    */
+    Overlay.windowResizeEvent = new CustomEvent("windowResize");
+
+    /**
+    * The DOM event handler used to fire the CustomEvent for window scroll
+    * @method YAHOO.widget.Overlay.windowScrollHandler
+    * @static
+    * @param {DOMEvent} e The DOM scroll event
+    */
+    Overlay.windowScrollHandler = function (e) {
+        var t = Event.getTarget(e);
+
+        // - Webkit (Safari 2/3) and Opera 9.2x bubble scroll events from elements to window
+        // - FF2/3 and IE6/7, Opera 9.5x don't bubble scroll events from elements to window
+        // - IE doesn't recognize scroll registered on the document.
+        //
+        // Also, when document view is scrolled, IE doesn't provide a target, 
+        // rest of the browsers set target to window.document, apart from opera 
+        // which sets target to window.
+        if (!t || t === window || t === window.document) {
+            if (UA.ie) {
+
+                if (! window.scrollEnd) {
+                    window.scrollEnd = -1;
+                }
+
+                clearTimeout(window.scrollEnd);
+        
+                window.scrollEnd = setTimeout(function () { 
+                    Overlay.windowScrollEvent.fire(); 
+                }, 1);
+        
+            } else {
+                Overlay.windowScrollEvent.fire();
+            }
+        }
+    };
+
+    /**
+    * The DOM event handler used to fire the CustomEvent for window resize
+    * @method YAHOO.widget.Overlay.windowResizeHandler
+    * @static
+    * @param {DOMEvent} e The DOM resize event
+    */
+    Overlay.windowResizeHandler = function (e) {
+
+        if (UA.ie) {
+            if (! window.resizeEnd) {
+                window.resizeEnd = -1;
+            }
+
+            clearTimeout(window.resizeEnd);
+
+            window.resizeEnd = setTimeout(function () {
+                Overlay.windowResizeEvent.fire(); 
+            }, 100);
+        } else {
+            Overlay.windowResizeEvent.fire();
+        }
+    };
+
+    /**
+    * A boolean that indicated whether the window resize and scroll events have 
+    * already been subscribed to.
+    * @property YAHOO.widget.Overlay._initialized
+    * @private
+    * @type Boolean
+    */
+    Overlay._initialized = null;
+
+    if (Overlay._initialized === null) {
+        Event.on(window, "scroll", Overlay.windowScrollHandler);
+        Event.on(window, "resize", Overlay.windowResizeHandler);
+        Overlay._initialized = true;
+    }
+
+    /**
+     * Internal map of special event types, which are provided
+     * by the instance. It maps the event type to the custom event 
+     * instance. Contains entries for the "windowScroll", "windowResize" and
+     * "textResize" static container events.
+     *
+     * @property YAHOO.widget.Overlay._TRIGGER_MAP
+     * @type Object
+     * @static
+     * @private
+     */
+    Overlay._TRIGGER_MAP = {
+        "windowScroll" : Overlay.windowScrollEvent,
+        "windowResize" : Overlay.windowResizeEvent,
+        "textResize"   : Module.textResizeEvent
+    };
+
+    YAHOO.extend(Overlay, Module, {
+
+        /**
+         * <p>
+         * Array of default event types which will trigger
+         * context alignment for the Overlay class.
+         * </p>
+         * <p>The array is empty by default for Overlay,
+         * but maybe populated in future releases, so classes extending
+         * Overlay which need to define their own set of CONTEXT_TRIGGERS
+         * should concatenate their super class's prototype.CONTEXT_TRIGGERS 
+         * value with their own array of values.
+         * </p>
+         * <p>
+         * E.g.:
+         * <code>CustomOverlay.prototype.CONTEXT_TRIGGERS = YAHOO.widget.Overlay.prototype.CONTEXT_TRIGGERS.concat(["windowScroll"]);</code>
+         * </p>
+         * 
+         * @property CONTEXT_TRIGGERS
+         * @type Array
+         * @final
+         */
+        CONTEXT_TRIGGERS : [],
+
+        /**
+        * The Overlay initialization method, which is executed for Overlay and  
+        * all of its subclasses. This method is automatically called by the 
+        * constructor, and  sets up all DOM references for pre-existing markup, 
+        * and creates required markup if it is not already present.
+        * @method init
+        * @param {String} el The element ID representing the Overlay <em>OR</em>
+        * @param {HTMLElement} el The element representing the Overlay
+        * @param {Object} userConfig The configuration object literal 
+        * containing the configuration that should be set for this Overlay. 
+        * See configuration documentation for more details.
+        */
+        init: function (el, userConfig) {
+
+            /*
+                 Note that we don't pass the user config in here yet because we
+                 only want it executed once, at the lowest subclass level
+            */
+
+            Overlay.superclass.init.call(this, el/*, userConfig*/);
+
+            this.beforeInitEvent.fire(Overlay);
+
+            Dom.addClass(this.element, Overlay.CSS_OVERLAY);
+
+            if (userConfig) {
+                this.cfg.applyConfig(userConfig, true);
+            }
+
+            if (this.platform == "mac" && UA.gecko) {
+
+                if (! Config.alreadySubscribed(this.showEvent,
+                    this.showMacGeckoScrollbars, this)) {
+
+                    this.showEvent.subscribe(this.showMacGeckoScrollbars, 
+                        this, true);
+
+                }
+
+                if (! Config.alreadySubscribed(this.hideEvent, 
+                    this.hideMacGeckoScrollbars, this)) {
+
+                    this.hideEvent.subscribe(this.hideMacGeckoScrollbars, 
+                        this, true);
+
+                }
+            }
+
+            this.initEvent.fire(Overlay);
+        },
+        
+        /**
+        * Initializes the custom events for Overlay which are fired  
+        * automatically at appropriate times by the Overlay class.
+        * @method initEvents
+        */
+        initEvents: function () {
+
+            Overlay.superclass.initEvents.call(this);
+
+            var SIGNATURE = CustomEvent.LIST;
+
+            /**
+            * CustomEvent fired before the Overlay is moved.
+            * @event beforeMoveEvent
+            * @param {Number} x x coordinate
+            * @param {Number} y y coordinate
+            */
+            this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
+            this.beforeMoveEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired after the Overlay is moved.
+            * @event moveEvent
+            * @param {Number} x x coordinate
+            * @param {Number} y y coordinate
+            */
+            this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
+            this.moveEvent.signature = SIGNATURE;
+
+        },
+        
+        /**
+        * Initializes the class's configurable properties which can be changed 
+        * using the Overlay's Config object (cfg).
+        * @method initDefaultConfig
+        */
+        initDefaultConfig: function () {
+    
+            Overlay.superclass.initDefaultConfig.call(this);
+
+            var cfg = this.cfg;
+
+            // Add overlay config properties //
+            
+            /**
+            * The absolute x-coordinate position of the Overlay
+            * @config x
+            * @type Number
+            * @default null
+            */
+            cfg.addProperty(DEFAULT_CONFIG.X.key, { 
+    
+                handler: this.configX, 
+                validator: DEFAULT_CONFIG.X.validator, 
+                suppressEvent: DEFAULT_CONFIG.X.suppressEvent, 
+                supercedes: DEFAULT_CONFIG.X.supercedes
+    
+            });
+
+            /**
+            * The absolute y-coordinate position of the Overlay
+            * @config y
+            * @type Number
+            * @default null
+            */
+            cfg.addProperty(DEFAULT_CONFIG.Y.key, {
+
+                handler: this.configY, 
+                validator: DEFAULT_CONFIG.Y.validator, 
+                suppressEvent: DEFAULT_CONFIG.Y.suppressEvent, 
+                supercedes: DEFAULT_CONFIG.Y.supercedes
+
+            });
+
+            /**
+            * An array with the absolute x and y positions of the Overlay
+            * @config xy
+            * @type Number[]
+            * @default null
+            */
+            cfg.addProperty(DEFAULT_CONFIG.XY.key, {
+                handler: this.configXY, 
+                suppressEvent: DEFAULT_CONFIG.XY.suppressEvent, 
+                supercedes: DEFAULT_CONFIG.XY.supercedes
+            });
+
+            /**
+            * <p>
+            * The array of context arguments for context-sensitive positioning. 
+            * </p>
+            *
+            * <p>
+            * The format of the array is: <code>[contextElementOrId, overlayCorner, contextCorner, arrayOfTriggerEvents (optional)]</code>, the
+            * the 4 array elements described in detail below:
+            * </p>
+            *
+            * <dl>
+            * <dt>contextElementOrId &#60;String|HTMLElement&#62;</dt>
+            * <dd>A reference to the context element to which the overlay should be aligned (or it's id).</dd>
+            * <dt>overlayCorner &#60;String&#62;</dt>
+            * <dd>The corner of the overlay which is to be used for alignment. This corner will be aligned to the 
+            * corner of the context element defined by the "contextCorner" entry which follows. Supported string values are: 
+            * "tr" (top right), "tl" (top left), "br" (bottom right), or "bl" (bottom left).</dd>
+            * <dt>contextCorner &#60;String&#62;</dt>
+            * <dd>The corner of the context element which is to be used for alignment. Supported string values are the same ones listed for the "overlayCorner" entry above.</dd>
+            * <dt>arrayOfTriggerEvents (optional) &#60;Array[String|CustomEvent]&#62;</dt>
+            * <dd>
+            * <p>
+            * By default, context alignment is a one time operation, aligning the Overlay to the context element when context configuration property is set, or when the <a href="#method_align">align</a> 
+            * method is invoked. However, you can use the optional "arrayOfTriggerEvents" entry to define the list of events which should force the overlay to re-align itself with the context element. 
+            * This is useful in situations where the layout of the document may change, resulting in the context element's position being modified.
+            * </p>
+            * <p>
+            * The array can contain either event type strings for events the instance publishes (e.g. "beforeShow") or CustomEvent instances. Additionally the following
+            * 3 static container event types are also currently supported : <code>"windowResize", "windowScroll", "textResize"</code> (defined in <a href="#property__TRIGGER_MAP">_TRIGGER_MAP</a> private property).
+            * </p>
+            * </dd>
+            * </dl>
+            *
+            * <p>
+            * For example, setting this property to <code>["img1", "tl", "bl"]</code> will 
+            * align the Overlay's top left corner to the bottom left corner of the
+            * context element with id "img1".
+            * </p>
+            * <p>
+            * Adding the optional trigger values: <code>["img1", "tl", "bl", ["beforeShow", "windowResize"]]</code>,
+            * will re-align the overlay position, whenever the "beforeShow" or "windowResize" events are fired.
+            * </p>
+            *
+            * @config context
+            * @type Array
+            * @default null
+            */
+            cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
+                handler: this.configContext, 
+                suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent, 
+                supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
+            });
+
+            /**
+            * Determines whether or not the Overlay should be anchored 
+            * to the center of the viewport.
+            * 
+            * <p>This property can be set to:</p>
+            * 
+            * <dl>
+            * <dt>true</dt>
+            * <dd>
+            * To enable fixed center positioning
+            * <p>
+            * When enabled, the overlay will 
+            * be positioned in the center of viewport when initially displayed, and 
+            * will remain in the center of the viewport whenever the window is 
+            * scrolled or resized.
+            * </p>
+            * <p>
+            * If the overlay is too big for the viewport, 
+            * it's top left corner will be aligned with the top left corner of the viewport.
+            * </p>
+            * </dd>
+            * <dt>false</dt>
+            * <dd>
+            * To disable fixed center positioning.
+            * <p>In this case the overlay can still be 
+            * centered as a one-off operation, by invoking the <code>center()</code> method,
+            * however it will not remain centered when the window is scrolled/resized.
+            * </dd>
+            * <dt>"contained"<dt>
+            * <dd>To enable fixed center positioning, as with the <code>true</code> option.
+            * <p>However, unlike setting the property to <code>true</code>, 
+            * when the property is set to <code>"contained"</code>, if the overlay is 
+            * too big for the viewport, it will not get automatically centered when the 
+            * user scrolls or resizes the window (until the window is large enough to contain the 
+            * overlay). This is useful in cases where the Overlay has both header and footer 
+            * UI controls which the user may need to access.
+            * </p>
+            * </dd>
+            * </dl>
+            *
+            * @config fixedcenter
+            * @type Boolean | String
+            * @default false
+            */
+            cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
+                handler: this.configFixedCenter,
+                value: DEFAULT_CONFIG.FIXED_CENTER.value, 
+                validator: DEFAULT_CONFIG.FIXED_CENTER.validator, 
+                supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
+            });
+    
+            /**
+            * CSS width of the Overlay.
+            * @config width
+            * @type String
+            * @default null
+            */
+            cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
+                handler: this.configWidth, 
+                suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent, 
+                supercedes: DEFAULT_CONFIG.WIDTH.supercedes
+            });
+
+            /**
+            * CSS height of the Overlay.
+            * @config height
+            * @type String
+            * @default null
+            */
+            cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
+                handler: this.configHeight, 
+                suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent, 
+                supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
+            });
+
+            /**
+            * Standard module element which should auto fill out the height of the Overlay if the height config property is set.
+            * Supported values are "header", "body", "footer".
+            *
+            * @config autofillheight
+            * @type String
+            * @default null
+            */
+            cfg.addProperty(DEFAULT_CONFIG.AUTO_FILL_HEIGHT.key, {
+                handler: this.configAutoFillHeight, 
+                value : DEFAULT_CONFIG.AUTO_FILL_HEIGHT.value,
+                validator : this._validateAutoFill,
+                supercedes: DEFAULT_CONFIG.AUTO_FILL_HEIGHT.supercedes
+            });
+
+            /**
+            * CSS z-index of the Overlay.
+            * @config zIndex
+            * @type Number
+            * @default null
+            */
+            cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
+                handler: this.configzIndex,
+                value: DEFAULT_CONFIG.ZINDEX.value
+            });
+
+            /**
+            * True if the Overlay should be prevented from being positioned 
+            * out of the viewport.
+            * @config constraintoviewport
+            * @type Boolean
+            * @default false
+            */
+            cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
+
+                handler: this.configConstrainToViewport, 
+                value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value, 
+                validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator, 
+                supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
+
+            });
+
+            /**
+            * @config iframe
+            * @description Boolean indicating whether or not the Overlay should 
+            * have an IFRAME shim; used to prevent SELECT elements from 
+            * poking through an Overlay instance in IE6.  When set to "true", 
+            * the iframe shim is created when the Overlay instance is intially
+            * made visible.
+            * @type Boolean
+            * @default true for IE6 and below, false for all other browsers.
+            */
+            cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
+
+                handler: this.configIframe, 
+                value: DEFAULT_CONFIG.IFRAME.value, 
+                validator: DEFAULT_CONFIG.IFRAME.validator, 
+                supercedes: DEFAULT_CONFIG.IFRAME.supercedes
+
+            });
+
+            /**
+            * @config preventcontextoverlap
+            * @description Boolean indicating whether or not the Overlay should overlap its 
+            * context element (defined using the "context" configuration property) when the 
+            * "constraintoviewport" configuration property is set to "true".
+            * @type Boolean
+            * @default false
+            */
+            cfg.addProperty(DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.key, {
+
+                value: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.value, 
+                validator: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.validator, 
+                supercedes: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.supercedes
+
+            });
+
+        },
+
+        /**
+        * Moves the Overlay to the specified position. This function is  
+        * identical to calling this.cfg.setProperty("xy", [x,y]);
+        * @method moveTo
+        * @param {Number} x The Overlay's new x position
+        * @param {Number} y The Overlay's new y position
+        */
+        moveTo: function (x, y) {
+            this.cfg.setProperty("xy", [x, y]);
+        },
+
+        /**
+        * Adds a CSS class ("hide-scrollbars") and removes a CSS class 
+        * ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
+        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
+        * @method hideMacGeckoScrollbars
+        */
+        hideMacGeckoScrollbars: function () {
+            Dom.replaceClass(this.element, "show-scrollbars", "hide-scrollbars");
+        },
+
+        /**
+        * Adds a CSS class ("show-scrollbars") and removes a CSS class 
+        * ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
+        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
+        * @method showMacGeckoScrollbars
+        */
+        showMacGeckoScrollbars: function () {
+            Dom.replaceClass(this.element, "hide-scrollbars", "show-scrollbars");
+        },
+
+        /**
+         * Internal implementation to set the visibility of the overlay in the DOM.
+         *
+         * @method _setDomVisibility
+         * @param {boolean} visible Whether to show or hide the Overlay's outer element
+         * @protected
+         */
+        _setDomVisibility : function(show) {
+            Dom.setStyle(this.element, "visibility", (show) ? "visible" : "hidden");
+
+            if (show) {
+                Dom.removeClass(this.element, "yui-overlay-hidden");
+            } else {
+                Dom.addClass(this.element, "yui-overlay-hidden");
+            }
+        },
+
+        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
+        /**
+        * The default event handler fired when the "visible" property is 
+        * changed.  This method is responsible for firing showEvent
+        * and hideEvent.
+        * @method configVisible
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configVisible: function (type, args, obj) {
+
+            var visible = args[0],
+                currentVis = Dom.getStyle(this.element, "visibility"),
+                effect = this.cfg.getProperty("effect"),
+                effectInstances = [],
+                isMacGecko = (this.platform == "mac" && UA.gecko),
+                alreadySubscribed = Config.alreadySubscribed,
+                eff, ei, e, i, j, k, h,
+                nEffects,
+                nEffectInstances;
+
+            if (currentVis == "inherit") {
+                e = this.element.parentNode;
+
+                while (e.nodeType != 9 && e.nodeType != 11) {
+                    currentVis = Dom.getStyle(e, "visibility");
+
+                    if (currentVis != "inherit") {
+                        break;
+                    }
+
+                    e = e.parentNode;
+                }
+
+                if (currentVis == "inherit") {
+                    currentVis = "visible";
+                }
+            }
+
+            if (effect) {
+                if (effect instanceof Array) {
+                    nEffects = effect.length;
+
+                    for (i = 0; i < nEffects; i++) {
+                        eff = effect[i];
+                        effectInstances[effectInstances.length] = 
+                            eff.effect(this, eff.duration);
+
+                    }
+                } else {
+                    effectInstances[effectInstances.length] = 
+                        effect.effect(this, effect.duration);
+                }
+            }
+
+            if (visible) { // Show
+                if (isMacGecko) {
+                    this.showMacGeckoScrollbars();
+                }
+
+                if (effect) { // Animate in
+                    if (visible) { // Animate in if not showing
+                        if (currentVis != "visible" || currentVis === "") {
+                            this.beforeShowEvent.fire();
+                            nEffectInstances = effectInstances.length;
+
+                            for (j = 0; j < nEffectInstances; j++) {
+                                ei = effectInstances[j];
+                                if (j === 0 && !alreadySubscribed(
+                                        ei.animateInCompleteEvent, 
+                                        this.showEvent.fire, this.showEvent)) {
+
+                                    /*
+                                         Delegate showEvent until end 
+                                         of animateInComplete
+                                    */
+
+                                    ei.animateInCompleteEvent.subscribe(
+                                     this.showEvent.fire, this.showEvent, true);
+                                }
+                                ei.animateIn();
+                            }
+                        }
+                    }
+                } else { // Show
+                    if (currentVis != "visible" || currentVis === "") {
+                        this.beforeShowEvent.fire();
+
+                        this._setDomVisibility(true);
+
+                        this.cfg.refireEvent("iframe");
+                        this.showEvent.fire();
+                    } else {
+                        this._setDomVisibility(true);
+                    }
+                }
+            } else { // Hide
+
+                if (isMacGecko) {
+                    this.hideMacGeckoScrollbars();
+                }
+
+                if (effect) { // Animate out if showing
+                    if (currentVis == "visible") {
+                        this.beforeHideEvent.fire();
+
+                        nEffectInstances = effectInstances.length;
+                        for (k = 0; k < nEffectInstances; k++) {
+                            h = effectInstances[k];
+    
+                            if (k === 0 && !alreadySubscribed(
+                                h.animateOutCompleteEvent, this.hideEvent.fire, 
+                                this.hideEvent)) {
+    
+                                /*
+                                     Delegate hideEvent until end 
+                                     of animateOutComplete
+                                */
+    
+                                h.animateOutCompleteEvent.subscribe(
+                                    this.hideEvent.fire, this.hideEvent, true);
+    
+                            }
+                            h.animateOut();
+                        }
+
+                    } else if (currentVis === "") {
+                        this._setDomVisibility(false);
+                    }
+
+                } else { // Simple hide
+
+                    if (currentVis == "visible" || currentVis === "") {
+                        this.beforeHideEvent.fire();
+                        this._setDomVisibility(false);
+                        this.hideEvent.fire();
+                    } else {
+                        this._setDomVisibility(false);
+                    }
+                }
+            }
+        },
+
+        /**
+        * Fixed center event handler used for centering on scroll/resize, but only if 
+        * the overlay is visible and, if "fixedcenter" is set to "contained", only if 
+        * the overlay fits within the viewport.
+        *
+        * @method doCenterOnDOMEvent
+        */
+        doCenterOnDOMEvent: function () {
+            var cfg = this.cfg,
+                fc = cfg.getProperty("fixedcenter");
+
+            if (cfg.getProperty("visible")) {
+                if (fc && (fc !== _CONTAINED || this.fitsInViewport())) {
+                    this.center();
+                }
+            }
+        },
+
+        /**
+         * Determines if the Overlay (including the offset value defined by Overlay.VIEWPORT_OFFSET) 
+         * will fit entirely inside the viewport, in both dimensions - width and height.
+         * 
+         * @method fitsInViewport
+         * @return boolean true if the Overlay will fit, false if not
+         */
+        fitsInViewport : function() {
+            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
+                element = this.element,
+                elementWidth = element.offsetWidth,
+                elementHeight = element.offsetHeight,
+                viewportWidth = Dom.getViewportWidth(),
+                viewportHeight = Dom.getViewportHeight();
+
+            return ((elementWidth + nViewportOffset < viewportWidth) && (elementHeight + nViewportOffset < viewportHeight));
+        },
+
+        /**
+        * The default event handler fired when the "fixedcenter" property 
+        * is changed.
+        * @method configFixedCenter
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configFixedCenter: function (type, args, obj) {
+
+            var val = args[0],
+                alreadySubscribed = Config.alreadySubscribed,
+                windowResizeEvent = Overlay.windowResizeEvent,
+                windowScrollEvent = Overlay.windowScrollEvent;
+
+            if (val) {
+                this.center();
+
+                if (!alreadySubscribed(this.beforeShowEvent, this.center)) {
+                    this.beforeShowEvent.subscribe(this.center);
+                }
+
+                if (!alreadySubscribed(windowResizeEvent, this.doCenterOnDOMEvent, this)) {
+                    windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
+                }
+
+                if (!alreadySubscribed(windowScrollEvent, this.doCenterOnDOMEvent, this)) {
+                    windowScrollEvent.subscribe(this.doCenterOnDOMEvent, this, true);
+                }
+
+            } else {
+                this.beforeShowEvent.unsubscribe(this.center);
+
+                windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
+                windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
+            }
+        },
+
+        /**
+        * The default event handler fired when the "height" property is changed.
+        * @method configHeight
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configHeight: function (type, args, obj) {
+
+            var height = args[0],
+                el = this.element;
+
+            Dom.setStyle(el, "height", height);
+            this.cfg.refireEvent("iframe");
+        },
+
+        /**
+         * The default event handler fired when the "autofillheight" property is changed.
+         * @method configAutoFillHeight
+         *
+         * @param {String} type The CustomEvent type (usually the property name)
+         * @param {Object[]} args The CustomEvent arguments. For configuration 
+         * handlers, args[0] will equal the newly applied value for the property.
+         * @param {Object} obj The scope object. For configuration handlers, 
+         * this will usually equal the owner.
+         */
+        configAutoFillHeight: function (type, args, obj) {
+            var fillEl = args[0],
+                cfg = this.cfg,
+                autoFillHeight = "autofillheight",
+                height = "height",
+                currEl = cfg.getProperty(autoFillHeight),
+                autoFill = this._autoFillOnHeightChange;
+
+            cfg.unsubscribeFromConfigEvent(height, autoFill);
+            Module.textResizeEvent.unsubscribe(autoFill);
+            this.changeContentEvent.unsubscribe(autoFill);
+
+            if (currEl && fillEl !== currEl && this[currEl]) {
+                Dom.setStyle(this[currEl], height, "");
+            }
+
+            if (fillEl) {
+                fillEl = Lang.trim(fillEl.toLowerCase());
+
+                cfg.subscribeToConfigEvent(height, autoFill, this[fillEl], this);
+                Module.textResizeEvent.subscribe(autoFill, this[fillEl], this);
+                this.changeContentEvent.subscribe(autoFill, this[fillEl], this);
+
+                cfg.setProperty(autoFillHeight, fillEl, true);
+            }
+        },
+
+        /**
+        * The default event handler fired when the "width" property is changed.
+        * @method configWidth
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configWidth: function (type, args, obj) {
+
+            var width = args[0],
+                el = this.element;
+
+            Dom.setStyle(el, "width", width);
+            this.cfg.refireEvent("iframe");
+        },
+
+        /**
+        * The default event handler fired when the "zIndex" property is changed.
+        * @method configzIndex
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configzIndex: function (type, args, obj) {
+
+            var zIndex = args[0],
+                el = this.element;
+
+            if (! zIndex) {
+                zIndex = Dom.getStyle(el, "zIndex");
+                if (! zIndex || isNaN(zIndex)) {
+                    zIndex = 0;
+                }
+            }
+
+            if (this.iframe || this.cfg.getProperty("iframe") === true) {
+                if (zIndex <= 0) {
+                    zIndex = 1;
+                }
+            }
+
+            Dom.setStyle(el, "zIndex", zIndex);
+            this.cfg.setProperty("zIndex", zIndex, true);
+
+            if (this.iframe) {
+                this.stackIframe();
+            }
+        },
+
+        /**
+        * The default event handler fired when the "xy" property is changed.
+        * @method configXY
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configXY: function (type, args, obj) {
+
+            var pos = args[0],
+                x = pos[0],
+                y = pos[1];
+
+            this.cfg.setProperty("x", x);
+            this.cfg.setProperty("y", y);
+
+            this.beforeMoveEvent.fire([x, y]);
+
+            x = this.cfg.getProperty("x");
+            y = this.cfg.getProperty("y");
+
+
+            this.cfg.refireEvent("iframe");
+            this.moveEvent.fire([x, y]);
+        },
+
+        /**
+        * The default event handler fired when the "x" property is changed.
+        * @method configX
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configX: function (type, args, obj) {
+
+            var x = args[0],
+                y = this.cfg.getProperty("y");
+
+            this.cfg.setProperty("x", x, true);
+            this.cfg.setProperty("y", y, true);
+
+            this.beforeMoveEvent.fire([x, y]);
+
+            x = this.cfg.getProperty("x");
+            y = this.cfg.getProperty("y");
+            
+            Dom.setX(this.element, x, true);
+
+            this.cfg.setProperty("xy", [x, y], true);
+
+            this.cfg.refireEvent("iframe");
+            this.moveEvent.fire([x, y]);
+        },
+
+        /**
+        * The default event handler fired when the "y" property is changed.
+        * @method configY
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configY: function (type, args, obj) {
+
+            var x = this.cfg.getProperty("x"),
+                y = args[0];
+
+            this.cfg.setProperty("x", x, true);
+            this.cfg.setProperty("y", y, true);
+
+            this.beforeMoveEvent.fire([x, y]);
+
+            x = this.cfg.getProperty("x");
+            y = this.cfg.getProperty("y");
+
+            Dom.setY(this.element, y, true);
+
+            this.cfg.setProperty("xy", [x, y], true);
+
+            this.cfg.refireEvent("iframe");
+            this.moveEvent.fire([x, y]);
+        },
+        
+        /**
+        * Shows the iframe shim, if it has been enabled.
+        * @method showIframe
+        */
+        showIframe: function () {
+
+            var oIFrame = this.iframe,
+                oParentNode;
+
+            if (oIFrame) {
+                oParentNode = this.element.parentNode;
+
+                if (oParentNode != oIFrame.parentNode) {
+                    this._addToParent(oParentNode, oIFrame);
+                }
+                oIFrame.style.display = "block";
+            }
+        },
+
+        /**
+        * Hides the iframe shim, if it has been enabled.
+        * @method hideIframe
+        */
+        hideIframe: function () {
+            if (this.iframe) {
+                this.iframe.style.display = "none";
+            }
+        },
+
+        /**
+        * Syncronizes the size and position of iframe shim to that of its 
+        * corresponding Overlay instance.
+        * @method syncIframe
+        */
+        syncIframe: function () {
+
+            var oIFrame = this.iframe,
+                oElement = this.element,
+                nOffset = Overlay.IFRAME_OFFSET,
+                nDimensionOffset = (nOffset * 2),
+                aXY;
+
+            if (oIFrame) {
+                // Size <iframe>
+                oIFrame.style.width = (oElement.offsetWidth + nDimensionOffset + "px");
+                oIFrame.style.height = (oElement.offsetHeight + nDimensionOffset + "px");
+
+                // Position <iframe>
+                aXY = this.cfg.getProperty("xy");
+
+                if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
+                    this.syncPosition();
+                    aXY = this.cfg.getProperty("xy");
+                }
+                Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
+            }
+        },
+
+        /**
+         * Sets the zindex of the iframe shim, if it exists, based on the zindex of
+         * the Overlay element. The zindex of the iframe is set to be one less 
+         * than the Overlay element's zindex.
+         * 
+         * <p>NOTE: This method will not bump up the zindex of the Overlay element
+         * to ensure that the iframe shim has a non-negative zindex.
+         * If you require the iframe zindex to be 0 or higher, the zindex of 
+         * the Overlay element should be set to a value greater than 0, before 
+         * this method is called.
+         * </p>
+         * @method stackIframe
+         */
+        stackIframe: function () {
+            if (this.iframe) {
+                var overlayZ = Dom.getStyle(this.element, "zIndex");
+                if (!YAHOO.lang.isUndefined(overlayZ) && !isNaN(overlayZ)) {
+                    Dom.setStyle(this.iframe, "zIndex", (overlayZ - 1));
+                }
+            }
+        },
+
+        /**
+        * The default event handler fired when the "iframe" property is changed.
+        * @method configIframe
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configIframe: function (type, args, obj) {
+
+            var bIFrame = args[0];
+
+            function createIFrame() {
+
+                var oIFrame = this.iframe,
+                    oElement = this.element,
+                    oParent;
+
+                if (!oIFrame) {
+                    if (!m_oIFrameTemplate) {
+                        m_oIFrameTemplate = document.createElement("iframe");
+
+                        if (this.isSecure) {
+                            m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
+                        }
+
+                        /*
+                            Set the opacity of the <iframe> to 0 so that it 
+                            doesn't modify the opacity of any transparent 
+                            elements that may be on top of it (like a shadow).
+                        */
+                        if (UA.ie) {
+                            m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
+                            /*
+                                 Need to set the "frameBorder" property to 0 
+                                 supress the default <iframe> border in IE.  
+                                 Setting the CSS "border" property alone 
+                                 doesn't supress it.
+                            */
+                            m_oIFrameTemplate.frameBorder = 0;
+                        }
+                        else {
+                            m_oIFrameTemplate.style.opacity = "0";
+                        }
+
+                        m_oIFrameTemplate.style.position = "absolute";
+                        m_oIFrameTemplate.style.border = "none";
+                        m_oIFrameTemplate.style.margin = "0";
+                        m_oIFrameTemplate.style.padding = "0";
+                        m_oIFrameTemplate.style.display = "none";
+                        m_oIFrameTemplate.tabIndex = -1;
+                    }
+
+                    oIFrame = m_oIFrameTemplate.cloneNode(false);
+                    oParent = oElement.parentNode;
+
+                    var parentNode = oParent || document.body;
+
+                    this._addToParent(parentNode, oIFrame);
+                    this.iframe = oIFrame;
+                }
+
+                /*
+                     Show the <iframe> before positioning it since the "setXY" 
+                     method of DOM requires the element be in the document 
+                     and visible.
+                */
+                this.showIframe();
+
+                /*
+                     Syncronize the size and position of the <iframe> to that 
+                     of the Overlay.
+                */
+                this.syncIframe();
+                this.stackIframe();
+
+                // Add event listeners to update the <iframe> when necessary
+                if (!this._hasIframeEventListeners) {
+                    this.showEvent.subscribe(this.showIframe);
+                    this.hideEvent.subscribe(this.hideIframe);
+                    this.changeContentEvent.subscribe(this.syncIframe);
+
+                    this._hasIframeEventListeners = true;
+                }
+            }
+
+            function onBeforeShow() {
+                createIFrame.call(this);
+                this.beforeShowEvent.unsubscribe(onBeforeShow);
+                this._iframeDeferred = false;
+            }
+
+            if (bIFrame) { // <iframe> shim is enabled
+
+                if (this.cfg.getProperty("visible")) {
+                    createIFrame.call(this);
+                } else {
+                    if (!this._iframeDeferred) {
+                        this.beforeShowEvent.subscribe(onBeforeShow);
+                        this._iframeDeferred = true;
+                    }
+                }
+
+            } else {    // <iframe> shim is disabled
+                this.hideIframe();
+
+                if (this._hasIframeEventListeners) {
+                    this.showEvent.unsubscribe(this.showIframe);
+                    this.hideEvent.unsubscribe(this.hideIframe);
+                    this.changeContentEvent.unsubscribe(this.syncIframe);
+
+                    this._hasIframeEventListeners = false;
+                }
+            }
+        },
+
+        /**
+         * Set's the container's XY value from DOM if not already set.
+         * 
+         * Differs from syncPosition, in that the XY value is only sync'd with DOM if 
+         * not already set. The method also refire's the XY config property event, so any
+         * beforeMove, Move event listeners are invoked.
+         * 
+         * @method _primeXYFromDOM
+         * @protected
+         */
+        _primeXYFromDOM : function() {
+            if (YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))) {
+                // Set CFG XY based on DOM XY
+                this.syncPosition();
+                // Account for XY being set silently in syncPosition (no moveTo fired/called)
+                this.cfg.refireEvent("xy");
+                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
+            }
+        },
+
+        /**
+        * The default event handler fired when the "constraintoviewport" 
+        * property is changed.
+        * @method configConstrainToViewport
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for 
+        * the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configConstrainToViewport: function (type, args, obj) {
+            var val = args[0];
+
+            if (val) {
+                if (! Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
+                    this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
+                }
+                if (! Config.alreadySubscribed(this.beforeShowEvent, this._primeXYFromDOM)) {
+                    this.beforeShowEvent.subscribe(this._primeXYFromDOM);
+                }
+            } else {
+                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
+                this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
+            }
+        },
+
+         /**
+        * The default event handler fired when the "context" property
+        * is changed.
+        * 
+        * @method configContext
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configContext: function (type, args, obj) {
+
+            var contextArgs = args[0],
+                contextEl,
+                elementMagnetCorner,
+                contextMagnetCorner,
+                triggers,
+                defTriggers = this.CONTEXT_TRIGGERS;
+
+            if (contextArgs) {
+
+                contextEl = contextArgs[0];
+                elementMagnetCorner = contextArgs[1];
+                contextMagnetCorner = contextArgs[2];
+                triggers = contextArgs[3];
+
+                if (defTriggers && defTriggers.length > 0) {
+                    triggers = (triggers || []).concat(defTriggers);
+                }
+
+                if (contextEl) {
+                    if (typeof contextEl == "string") {
+                        this.cfg.setProperty("context", [
+                                document.getElementById(contextEl), 
+                                elementMagnetCorner,
+                                contextMagnetCorner,
+                                triggers ],
+                                true);
+                    }
+
+                    if (elementMagnetCorner && contextMagnetCorner) {
+                        this.align(elementMagnetCorner, contextMagnetCorner);
+                    }
+
+                    if (this._contextTriggers) {
+                        // Unsubscribe Old Set
+                        this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
+                    }
+
+                    if (triggers) {
+                        // Subscribe New Set
+                        this._processTriggers(triggers, _SUBSCRIBE, this._alignOnTrigger);
+                        this._contextTriggers = triggers;
+                    }
+                }
+            }
+        },
+
+        /**
+         * Custom Event handler for context alignment triggers. Invokes the align method
+         * 
+         * @method _alignOnTrigger
+         * @protected
+         * 
+         * @param {String} type The event type (not used by the default implementation)
+         * @param {Any[]} args The array of arguments for the trigger event (not used by the default implementation)
+         */
+        _alignOnTrigger: function(type, args) {
+            this.align();
+        },
+
+        /**
+         * Helper method to locate the custom event instance for the event name string
+         * passed in. As a convenience measure, any custom events passed in are returned.
+         *
+         * @method _findTriggerCE
+         * @private
+         *
+         * @param {String|CustomEvent} t Either a CustomEvent, or event type (e.g. "windowScroll") for which a 
+         * custom event instance needs to be looked up from the Overlay._TRIGGER_MAP.
+         */
+        _findTriggerCE : function(t) {
+            var tce = null;
+            if (t instanceof CustomEvent) {
+                tce = t;
+            } else if (Overlay._TRIGGER_MAP[t]) {
+                tce = Overlay._TRIGGER_MAP[t];
+            }
+            return tce;
+        },
+
+        /**
+         * Utility method that subscribes or unsubscribes the given 
+         * function from the list of trigger events provided.
+         *
+         * @method _processTriggers
+         * @protected 
+         *
+         * @param {Array[String|CustomEvent]} triggers An array of either CustomEvents, event type strings 
+         * (e.g. "beforeShow", "windowScroll") to/from which the provided function should be 
+         * subscribed/unsubscribed respectively.
+         *
+         * @param {String} mode Either "subscribe" or "unsubscribe", specifying whether or not
+         * we are subscribing or unsubscribing trigger listeners
+         * 
+         * @param {Function} fn The function to be subscribed/unsubscribed to/from the trigger event.
+         * Context is always set to the overlay instance, and no additional object argument 
+         * get passed to the subscribed function.
+         */
+        _processTriggers : function(triggers, mode, fn) {
+            var t, tce;
+
+            for (var i = 0, l = triggers.length; i < l; ++i) {
+                t = triggers[i];
+                tce = this._findTriggerCE(t);
+                if (tce) {
+                    tce[mode](fn, this, true);
+                } else {
+                    this[mode](t, fn);
+                }
+            }
+        },
+
+        // END BUILT-IN PROPERTY EVENT HANDLERS //
+        /**
+        * Aligns the Overlay to its context element using the specified corner 
+        * points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, 
+        * and BOTTOM_RIGHT.
+        * @method align
+        * @param {String} elementAlign  The String representing the corner of 
+        * the Overlay that should be aligned to the context element
+        * @param {String} contextAlign  The corner of the context element 
+        * that the elementAlign corner should stick to.
+        */
+        align: function (elementAlign, contextAlign) {
+
+            var contextArgs = this.cfg.getProperty("context"),
+                me = this,
+                context,
+                element,
+                contextRegion;
+
+            function doAlign(v, h) {
+    
+                switch (elementAlign) {
+    
+                case Overlay.TOP_LEFT:
+                    me.moveTo(h, v);
+                    break;
+    
+                case Overlay.TOP_RIGHT:
+                    me.moveTo((h - element.offsetWidth), v);
+                    break;
+    
+                case Overlay.BOTTOM_LEFT:
+                    me.moveTo(h, (v - element.offsetHeight));
+                    break;
+    
+                case Overlay.BOTTOM_RIGHT:
+                    me.moveTo((h - element.offsetWidth), 
+                        (v - element.offsetHeight));
+                    break;
+                }
+            }
+    
+    
+            if (contextArgs) {
+            
+                context = contextArgs[0];
+                element = this.element;
+                me = this;
+                
+                if (! elementAlign) {
+                    elementAlign = contextArgs[1];
+                }
+                
+                if (! contextAlign) {
+                    contextAlign = contextArgs[2];
+                }
+                
+                if (element && context) {
+                    contextRegion = Dom.getRegion(context);
+
+                    switch (contextAlign) {
+    
+                    case Overlay.TOP_LEFT:
+                        doAlign(contextRegion.top, contextRegion.left);
+                        break;
+    
+                    case Overlay.TOP_RIGHT:
+                        doAlign(contextRegion.top, contextRegion.right);
+                        break;
+    
+                    case Overlay.BOTTOM_LEFT:
+                        doAlign(contextRegion.bottom, contextRegion.left);
+                        break;
+    
+                    case Overlay.BOTTOM_RIGHT:
+                        doAlign(contextRegion.bottom, contextRegion.right);
+                        break;
+                    }
+    
+                }
+    
+            }
+            
+        },
+
+        /**
+        * The default event handler executed when the moveEvent is fired, if the 
+        * "constraintoviewport" is set to true.
+        * @method enforceConstraints
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        enforceConstraints: function (type, args, obj) {
+            var pos = args[0];
+            
+            var cXY = this.getConstrainedXY(pos[0], pos[1]);
+            this.cfg.setProperty("x", cXY[0], true);
+            this.cfg.setProperty("y", cXY[1], true);
+            this.cfg.setProperty("xy", cXY, true);
+        },
+
+
+        /**
+         * Given x coordinate value, returns the calculated x coordinate required to 
+         * position the Overlay if it is to be constrained to the viewport, based on the 
+         * current element size, viewport dimensions and scroll values.
+         *
+         * @param {Number} x The X coordinate value to be constrained
+         * @return {Number} The constrained x coordinate
+         */            
+        getConstrainedX: function (x) {
+
+            var oOverlay = this,
+                oOverlayEl = oOverlay.element,
+                nOverlayOffsetWidth = oOverlayEl.offsetWidth,
+
+                nViewportOffset = Overlay.VIEWPORT_OFFSET,
+                viewPortWidth = Dom.getViewportWidth(),
+                scrollX = Dom.getDocumentScrollLeft(),
+
+                bCanConstrain = (nOverlayOffsetWidth + nViewportOffset < viewPortWidth),
+
+                aContext = this.cfg.getProperty("context"),
+                oContextEl,
+                nContextElX,
+                nContextElWidth,
+
+                bFlipped = false,
+
+                nLeftRegionWidth,
+                nRightRegionWidth,
+
+                leftConstraint = scrollX + nViewportOffset,
+                rightConstraint = scrollX + viewPortWidth - nOverlayOffsetWidth - nViewportOffset,
+
+                xNew = x,
+
+                oOverlapPositions = {
+
+                    "tltr": true,
+                    "blbr": true,
+                    "brbl": true,
+                    "trtl": true
+                
+                };
+
+
+            var flipHorizontal = function () {
+            
+                var nNewX;
+            
+                if ((oOverlay.cfg.getProperty("x") - scrollX) > nContextElX) {
+                    nNewX = (nContextElX - nOverlayOffsetWidth);
+                }
+                else {
+                    nNewX = (nContextElX + nContextElWidth);
+                }
+                
+    
+                oOverlay.cfg.setProperty("x", (nNewX + scrollX), true);
+    
+                return nNewX;
+    
+            };
+
+
+
+            /*
+                 Uses the context element's position to calculate the availble width 
+                 to the right and left of it to display its corresponding Overlay.
+            */
+
+            var getDisplayRegionWidth = function () {
+
+                // The Overlay is to the right of the context element
+
+                if ((oOverlay.cfg.getProperty("x") - scrollX) > nContextElX) {
+                    return (nRightRegionWidth - nViewportOffset);
+                }
+                else { // The Overlay is to the left of the context element
+                    return (nLeftRegionWidth - nViewportOffset);
+                }
+            
+            };
+    
+
+            /*
+                Positions the Overlay to the left or right of the context element so that it remains 
+                inside the viewport.
+            */
+    
+            var setHorizontalPosition = function () {
+            
+                var nDisplayRegionWidth = getDisplayRegionWidth(),
+                    fnReturnVal;
+
+                if (nOverlayOffsetWidth > nDisplayRegionWidth) {
+        
+                    if (bFlipped) {
+        
+                        /*
+                             All possible positions and values have been 
+                             tried, but none were successful, so fall back 
+                             to the original size and position.
+                        */
+    
+                        flipHorizontal();
+                        
+                    }
+                    else {
+        
+                        flipHorizontal();
+
+                        bFlipped = true;
+        
+                        fnReturnVal = setHorizontalPosition();
+        
+                    }
+                
+                }
+        
+                return fnReturnVal;
+            
+            };
+
+            // Determine if the current value for the Overlay's "x" configuration property will
+            // result in the Overlay being positioned outside the boundaries of the viewport
+            
+            if (x < leftConstraint || x > rightConstraint) {
+
+                // The current value for the Overlay's "x" configuration property WILL
+                // result in the Overlay being positioned outside the boundaries of the viewport
+
+                if (bCanConstrain) {
+
+                    // If the "preventcontextoverlap" configuration property is set to "true", 
+                    // try to flip the Overlay to both keep it inside the boundaries of the 
+                    // viewport AND from overlaping its context element.
+    
+                    if (this.cfg.getProperty("preventcontextoverlap") && aContext && 
+                        oOverlapPositions[(aContext[1] + aContext[2])]) {
+        
+                        oContextEl = aContext[0];
+                        nContextElX = Dom.getX(oContextEl) - scrollX;
+                        nContextElWidth = oContextEl.offsetWidth;
+                        nLeftRegionWidth = nContextElX;
+                        nRightRegionWidth = (viewPortWidth - (nContextElX + nContextElWidth));
+        
+                        setHorizontalPosition();
+                        
+                        xNew = this.cfg.getProperty("x");
+                    
+                    }
+                    else {
+
+                        if (x < leftConstraint) {
+                            xNew = leftConstraint;
+                        } else if (x > rightConstraint) {
+                            xNew = rightConstraint;
+                        }
+
+                    }
+
+                } else {
+                    // The "x" configuration property cannot be set to a value that will keep
+                    // entire Overlay inside the boundary of the viewport.  Therefore, set  
+                    // the "x" configuration property to scrollY to keep as much of the 
+                    // Overlay inside the viewport as possible.                
+                    xNew = nViewportOffset + scrollX;
+                }
+
+            }
+
+            return xNew;
+        
+        },
+
+
+        /**
+         * Given y coordinate value, returns the calculated y coordinate required to 
+         * position the Overlay if it is to be constrained to the viewport, based on the 
+         * current element size, viewport dimensions and scroll values.
+         *
+         * @param {Number} y The Y coordinate value to be constrained
+         * @return {Number} The constrained y coordinate
+         */            
+        getConstrainedY: function (y) {
+
+            var oOverlay = this,
+                oOverlayEl = oOverlay.element,
+                nOverlayOffsetHeight = oOverlayEl.offsetHeight,
+            
+                nViewportOffset = Overlay.VIEWPORT_OFFSET,
+                viewPortHeight = Dom.getViewportHeight(),
+                scrollY = Dom.getDocumentScrollTop(),
+
+                bCanConstrain = (nOverlayOffsetHeight + nViewportOffset < viewPortHeight),
+
+                aContext = this.cfg.getProperty("context"),
+                oContextEl,
+                nContextElY,
+                nContextElHeight,
+
+                bFlipped = false,
+
+                nTopRegionHeight,
+                nBottomRegionHeight,
+
+                topConstraint = scrollY + nViewportOffset,
+                bottomConstraint = scrollY + viewPortHeight - nOverlayOffsetHeight - nViewportOffset,
+
+                yNew = y,
+                
+                oOverlapPositions = {
+                    "trbr": true,
+                    "tlbl": true,
+                    "bltl": true,
+                    "brtr": true
+                };
+
+
+            var flipVertical = function () {
+
+                var nNewY;
+            
+                // The Overlay is below the context element, flip it above
+                if ((oOverlay.cfg.getProperty("y") - scrollY) > nContextElY) { 
+                    nNewY = (nContextElY - nOverlayOffsetHeight);
+                }
+                else { // The Overlay is above the context element, flip it below
+                    nNewY = (nContextElY + nContextElHeight);
+                }
+    
+                oOverlay.cfg.setProperty("y", (nNewY + scrollY), true);
+                
+                return nNewY;
+            
+            };
+
+
+            /*
+                 Uses the context element's position to calculate the availble height 
+                 above and below it to display its corresponding Overlay.
+            */
+
+            var getDisplayRegionHeight = function () {
+
+                // The Overlay is below the context element
+                if ((oOverlay.cfg.getProperty("y") - scrollY) > nContextElY) {
+                    return (nBottomRegionHeight - nViewportOffset);                            
+                }
+                else { // The Overlay is above the context element
+                    return (nTopRegionHeight - nViewportOffset);                               
+                }
+        
+            };
+
+
+            /*
+                Trys to place the Overlay in the best possible position (either above or 
+                below its corresponding context element).
+            */
+        
+            var setVerticalPosition = function () {
+        
+                var nDisplayRegionHeight = getDisplayRegionHeight(),
+                    fnReturnVal;
+                    
+
+                if (nOverlayOffsetHeight > nDisplayRegionHeight) {
+                   
+                    if (bFlipped) {
+        
+                        /*
+                             All possible positions and values for the 
+                             "maxheight" configuration property have been 
+                             tried, but none were successful, so fall back 
+                             to the original size and position.
+                        */
+    
+                        flipVertical();
+                        
+                    }
+                    else {
+        
+                        flipVertical();
+
+                        bFlipped = true;
+        
+                        fnReturnVal = setVerticalPosition();
+        
+                    }
+                
+                }
+        
+                return fnReturnVal;
+        
+            };
+
+
+            // Determine if the current value for the Overlay's "y" configuration property will
+            // result in the Overlay being positioned outside the boundaries of the viewport
+
+            if (y < topConstraint || y  > bottomConstraint) {
+        
+                // The current value for the Overlay's "y" configuration property WILL
+                // result in the Overlay being positioned outside the boundaries of the viewport
+
+                if (bCanConstrain) {   
+
+                    // If the "preventcontextoverlap" configuration property is set to "true", 
+                    // try to flip the Overlay to both keep it inside the boundaries of the 
+                    // viewport AND from overlaping its context element.
+        
+                    if (this.cfg.getProperty("preventcontextoverlap") && aContext && 
+                        oOverlapPositions[(aContext[1] + aContext[2])]) {
+        
+                        oContextEl = aContext[0];
+                        nContextElHeight = oContextEl.offsetHeight;
+                        nContextElY = (Dom.getY(oContextEl) - scrollY);
+        
+                        nTopRegionHeight = nContextElY;
+                        nBottomRegionHeight = (viewPortHeight - (nContextElY + nContextElHeight));
+        
+                        setVerticalPosition();
+        
+                        yNew = oOverlay.cfg.getProperty("y");
+        
+                    }
+                    else {
+
+                        if (y < topConstraint) {
+                            yNew  = topConstraint;
+                        } else if (y  > bottomConstraint) {
+                            yNew  = bottomConstraint;
+                        }
+                    
+                    }
+                
+                }
+                else {
+                
+                    // The "y" configuration property cannot be set to a value that will keep
+                    // entire Overlay inside the boundary of the viewport.  Therefore, set  
+                    // the "y" configuration property to scrollY to keep as much of the 
+                    // Overlay inside the viewport as possible.
+                
+                    yNew = nViewportOffset + scrollY;
+                }
+        
+            }
+
+            return yNew;
+        },
+
+
+        /**
+         * Given x, y coordinate values, returns the calculated coordinates required to 
+         * position the Overlay if it is to be constrained to the viewport, based on the 
+         * current element size, viewport dimensions and scroll values.
+         *
+         * @param {Number} x The X coordinate value to be constrained
+         * @param {Number} y The Y coordinate value to be constrained
+         * @return {Array} The constrained x and y coordinates at index 0 and 1 respectively;
+         */
+        getConstrainedXY: function(x, y) {
+            return [this.getConstrainedX(x), this.getConstrainedY(y)];
+        },
+
+        /**
+        * Centers the container in the viewport.
+        * @method center
+        */
+        center: function () {
+
+            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
+                elementWidth = this.element.offsetWidth,
+                elementHeight = this.element.offsetHeight,
+                viewPortWidth = Dom.getViewportWidth(),
+                viewPortHeight = Dom.getViewportHeight(),
+                x,
+                y;
+
+            if (elementWidth < viewPortWidth) {
+                x = (viewPortWidth / 2) - (elementWidth / 2) + Dom.getDocumentScrollLeft();
+            } else {
+                x = nViewportOffset + Dom.getDocumentScrollLeft();
+            }
+
+            if (elementHeight < viewPortHeight) {
+                y = (viewPortHeight / 2) - (elementHeight / 2) + Dom.getDocumentScrollTop();
+            } else {
+                y = nViewportOffset + Dom.getDocumentScrollTop();
+            }
+
+            this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
+            this.cfg.refireEvent("iframe");
+
+            if (UA.webkit) {
+                this.forceContainerRedraw();
+            }
+        },
+
+        /**
+        * Synchronizes the Panel's "xy", "x", and "y" properties with the 
+        * Panel's position in the DOM. This is primarily used to update  
+        * position information during drag & drop.
+        * @method syncPosition
+        */
+        syncPosition: function () {
+
+            var pos = Dom.getXY(this.element);
+
+            this.cfg.setProperty("x", pos[0], true);
+            this.cfg.setProperty("y", pos[1], true);
+            this.cfg.setProperty("xy", pos, true);
+
+        },
+
+        /**
+        * Event handler fired when the resize monitor element is resized.
+        * @method onDomResize
+        * @param {DOMEvent} e The resize DOM event
+        * @param {Object} obj The scope object
+        */
+        onDomResize: function (e, obj) {
+
+            var me = this;
+
+            Overlay.superclass.onDomResize.call(this, e, obj);
+
+            setTimeout(function () {
+                me.syncPosition();
+                me.cfg.refireEvent("iframe");
+                me.cfg.refireEvent("context");
+            }, 0);
+        },
+
+        /**
+         * Determines the content box height of the given element (height of the element, without padding or borders) in pixels.
+         *
+         * @method _getComputedHeight
+         * @private
+         * @param {HTMLElement} el The element for which the content height needs to be determined
+         * @return {Number} The content box height of the given element, or null if it could not be determined.
+         */
+        _getComputedHeight : (function() {
+
+            if (document.defaultView && document.defaultView.getComputedStyle) {
+                return function(el) {
+                    var height = null;
+                    if (el.ownerDocument && el.ownerDocument.defaultView) {
+                        var computed = el.ownerDocument.defaultView.getComputedStyle(el, '');
+                        if (computed) {
+                            height = parseInt(computed.height, 10);
+                        }
+                    }
+                    return (Lang.isNumber(height)) ? height : null;
+                };
+            } else {
+                return function(el) {
+                    var height = null;
+                    if (el.style.pixelHeight) {
+                        height = el.style.pixelHeight;
+                    }
+                    return (Lang.isNumber(height)) ? height : null;
+                };
+            }
+        })(),
+
+        /**
+         * autofillheight validator. Verifies that the autofill value is either null 
+         * or one of the strings : "body", "header" or "footer".
+         *
+         * @method _validateAutoFillHeight
+         * @protected
+         * @param {String} val
+         * @return true, if valid, false otherwise
+         */
+        _validateAutoFillHeight : function(val) {
+            return (!val) || (Lang.isString(val) && Overlay.STD_MOD_RE.test(val));
+        },
+
+        /**
+         * The default custom event handler executed when the overlay's height is changed, 
+         * if the autofillheight property has been set.
+         *
+         * @method _autoFillOnHeightChange
+         * @protected
+         * @param {String} type The event type
+         * @param {Array} args The array of arguments passed to event subscribers
+         * @param {HTMLElement} el The header, body or footer element which is to be resized to fill
+         * out the containers height
+         */
+        _autoFillOnHeightChange : function(type, args, el) {
+            var height = this.cfg.getProperty("height");
+            if ((height && height !== "auto") || (height === 0)) {
+                this.fillHeight(el);
+            }
+        },
+
+        /**
+         * Returns the sub-pixel height of the el, using getBoundingClientRect, if available,
+         * otherwise returns the offsetHeight
+         * @method _getPreciseHeight
+         * @private
+         * @param {HTMLElement} el
+         * @return {Float} The sub-pixel height if supported by the browser, else the rounded height.
+         */
+        _getPreciseHeight : function(el) {
+            var height = el.offsetHeight;
+
+            if (el.getBoundingClientRect) {
+                var rect = el.getBoundingClientRect();
+                height = rect.bottom - rect.top;
+            }
+
+            return height;
+        },
+
+        /**
+         * <p>
+         * Sets the height on the provided header, body or footer element to 
+         * fill out the height of the container. It determines the height of the 
+         * containers content box, based on it's configured height value, and 
+         * sets the height of the autofillheight element to fill out any 
+         * space remaining after the other standard module element heights 
+         * have been accounted for.
+         * </p>
+         * <p><strong>NOTE:</strong> This method is not designed to work if an explicit 
+         * height has not been set on the container, since for an "auto" height container, 
+         * the heights of the header/body/footer will drive the height of the container.</p>
+         *
+         * @method fillHeight
+         * @param {HTMLElement} el The element which should be resized to fill out the height
+         * of the container element.
+         */
+        fillHeight : function(el) {
+            if (el) {
+                var container = this.innerElement || this.element,
+                    containerEls = [this.header, this.body, this.footer],
+                    containerEl,
+                    total = 0,
+                    filled = 0,
+                    remaining = 0,
+                    validEl = false;
+
+                for (var i = 0, l = containerEls.length; i < l; i++) {
+                    containerEl = containerEls[i];
+                    if (containerEl) {
+                        if (el !== containerEl) {
+                            filled += this._getPreciseHeight(containerEl);
+                        } else {
+                            validEl = true;
+                        }
+                    }
+                }
+
+                if (validEl) {
+
+                    if (UA.ie || UA.opera) {
+                        // Need to set height to 0, to allow height to be reduced
+                        Dom.setStyle(el, 'height', 0 + 'px');
+                    }
+
+                    total = this._getComputedHeight(container);
+
+                    // Fallback, if we can't get computed value for content height
+                    if (total === null) {
+                        Dom.addClass(container, "yui-override-padding");
+                        total = container.clientHeight; // Content, No Border, 0 Padding (set by yui-override-padding)
+                        Dom.removeClass(container, "yui-override-padding");
+                    }
+    
+                    remaining = Math.max(total - filled, 0);
+    
+                    Dom.setStyle(el, "height", remaining + "px");
+    
+                    // Re-adjust height if required, to account for el padding and border
+                    if (el.offsetHeight != remaining) {
+                        remaining = Math.max(remaining - (el.offsetHeight - remaining), 0);
+                    }
+                    Dom.setStyle(el, "height", remaining + "px");
+                }
+            }
+        },
+
+        /**
+        * Places the Overlay on top of all other instances of 
+        * YAHOO.widget.Overlay.
+        * @method bringToTop
+        */
+        bringToTop: function () {
+
+            var aOverlays = [],
+                oElement = this.element;
+
+            function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
+
+                var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
+                    sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
+
+                    nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 0 : parseInt(sZIndex1, 10),
+                    nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 0 : parseInt(sZIndex2, 10);
+
+                if (nZIndex1 > nZIndex2) {
+                    return -1;
+                } else if (nZIndex1 < nZIndex2) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+
+            function isOverlayElement(p_oElement) {
+
+                var isOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
+                    Panel = YAHOO.widget.Panel;
+
+                if (isOverlay && !Dom.isAncestor(oElement, p_oElement)) {
+                    if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
+                        aOverlays[aOverlays.length] = p_oElement.parentNode;
+                    } else {
+                        aOverlays[aOverlays.length] = p_oElement;
+                    }
+                }
+            }
+
+            Dom.getElementsBy(isOverlayElement, "DIV", document.body);
+
+            aOverlays.sort(compareZIndexDesc);
+
+            var oTopOverlay = aOverlays[0],
+                nTopZIndex;
+
+            if (oTopOverlay) {
+                nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
+
+                if (!isNaN(nTopZIndex)) {
+                    var bRequiresBump = false;
+
+                    if (oTopOverlay != oElement) {
+                        bRequiresBump = true;
+                    } else if (aOverlays.length > 1) {
+                        var nNextZIndex = Dom.getStyle(aOverlays[1], "zIndex");
+                        // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
+                        if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
+                            bRequiresBump = true;
+                        }
+                    }
+                    if (bRequiresBump) {
+                        this.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
+                    }
+                }
+            }
+        },
+
+        /**
+        * Removes the Overlay element from the DOM and sets all child 
+        * elements to null.
+        * @method destroy
+        */
+        destroy: function () {
+
+            if (this.iframe) {
+                this.iframe.parentNode.removeChild(this.iframe);
+            }
+
+            this.iframe = null;
+
+            Overlay.windowResizeEvent.unsubscribe(
+                this.doCenterOnDOMEvent, this);
+    
+            Overlay.windowScrollEvent.unsubscribe(
+                this.doCenterOnDOMEvent, this);
+
+            Module.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);
+
+            Overlay.superclass.destroy.call(this);
+        },
+
+        /**
+         * Can be used to force the container to repaint/redraw it's contents.
+         * <p>
+         * By default applies and then removes a 1px bottom margin through the 
+         * application/removal of a "yui-force-redraw" class.
+         * </p>
+         * <p>
+         * It is currently used by Overlay to force a repaint for webkit 
+         * browsers, when centering.
+         * </p>
+         * @method forceContainerRedraw
+         */
+        forceContainerRedraw : function() {
+            var c = this;
+            Dom.addClass(c.element, "yui-force-redraw");
+            setTimeout(function() {
+                Dom.removeClass(c.element, "yui-force-redraw");
+            }, 0);
+        },
+
+        /**
+        * Returns a String representation of the object.
+        * @method toString
+        * @return {String} The string representation of the Overlay.
+        */
+        toString: function () {
+            return "Overlay " + this.id;
+        }
+
+    });
+}());
+
+(function () {
+
+    /**
+    * OverlayManager is used for maintaining the focus status of 
+    * multiple Overlays.
+    * @namespace YAHOO.widget
+    * @namespace YAHOO.widget
+    * @class OverlayManager
+    * @constructor
+    * @param {Array} overlays Optional. A collection of Overlays to register 
+    * with the manager.
+    * @param {Object} userConfig  The object literal representing the user 
+    * configuration of the OverlayManager
+    */
+    YAHOO.widget.OverlayManager = function (userConfig) {
+        this.init(userConfig);
+    };
+
+    var Overlay = YAHOO.widget.Overlay,
+        Event = YAHOO.util.Event,
+        Dom = YAHOO.util.Dom,
+        Config = YAHOO.util.Config,
+        CustomEvent = YAHOO.util.CustomEvent,
+        OverlayManager = YAHOO.widget.OverlayManager;
+
+    /**
+    * The CSS class representing a focused Overlay
+    * @property OverlayManager.CSS_FOCUSED
+    * @static
+    * @final
+    * @type String
+    */
+    OverlayManager.CSS_FOCUSED = "focused";
+
+    OverlayManager.prototype = {
+
+        /**
+        * The class's constructor function
+        * @property contructor
+        * @type Function
+        */
+        constructor: OverlayManager,
+
+        /**
+        * The array of Overlays that are currently registered
+        * @property overlays
+        * @type YAHOO.widget.Overlay[]
+        */
+        overlays: null,
+
+        /**
+        * Initializes the default configuration of the OverlayManager
+        * @method initDefaultConfig
+        */
+        initDefaultConfig: function () {
+            /**
+            * The collection of registered Overlays in use by 
+            * the OverlayManager
+            * @config overlays
+            * @type YAHOO.widget.Overlay[]
+            * @default null
+            */
+            this.cfg.addProperty("overlays", { suppressEvent: true } );
+
+            /**
+            * The default DOM event that should be used to focus an Overlay
+            * @config focusevent
+            * @type String
+            * @default "mousedown"
+            */
+            this.cfg.addProperty("focusevent", { value: "mousedown" } );
+        },
+
+        /**
+        * Initializes the OverlayManager
+        * @method init
+        * @param {Overlay[]} overlays Optional. A collection of Overlays to 
+        * register with the manager.
+        * @param {Object} userConfig  The object literal representing the user 
+        * configuration of the OverlayManager
+        */
+        init: function (userConfig) {
+
+            /**
+            * The OverlayManager's Config object used for monitoring 
+            * configuration properties.
+            * @property cfg
+            * @type Config
+            */
+            this.cfg = new Config(this);
+
+            this.initDefaultConfig();
+
+            if (userConfig) {
+                this.cfg.applyConfig(userConfig, true);
+            }
+            this.cfg.fireQueue();
+
+            /**
+            * The currently activated Overlay
+            * @property activeOverlay
+            * @private
+            * @type YAHOO.widget.Overlay
+            */
+            var activeOverlay = null;
+
+            /**
+            * Returns the currently focused Overlay
+            * @method getActive
+            * @return {Overlay} The currently focused Overlay
+            */
+            this.getActive = function () {
+                return activeOverlay;
+            };
+
+            /**
+            * Focuses the specified Overlay
+            * @method focus
+            * @param {Overlay} overlay The Overlay to focus
+            * @param {String} overlay The id of the Overlay to focus
+            */
+            this.focus = function (overlay) {
+                var o = this.find(overlay);
+                if (o) {
+                    o.focus();
+                }
+            };
+
+            /**
+            * Removes the specified Overlay from the manager
+            * @method remove
+            * @param {Overlay} overlay The Overlay to remove
+            * @param {String} overlay The id of the Overlay to remove
+            */
+            this.remove = function (overlay) {
+
+                var o = this.find(overlay), 
+                        originalZ;
+
+                if (o) {
+                    if (activeOverlay == o) {
+                        activeOverlay = null;
+                    }
+
+                    var bDestroyed = (o.element === null && o.cfg === null) ? true : false;
+
+                    if (!bDestroyed) {
+                        // Set it's zindex so that it's sorted to the end.
+                        originalZ = Dom.getStyle(o.element, "zIndex");
+                        o.cfg.setProperty("zIndex", -1000, true);
+                    }
+
+                    this.overlays.sort(this.compareZIndexDesc);
+                    this.overlays = this.overlays.slice(0, (this.overlays.length - 1));
+
+                    o.hideEvent.unsubscribe(o.blur);
+                    o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
+                    o.focusEvent.unsubscribe(this._onOverlayFocusHandler, o);
+                    o.blurEvent.unsubscribe(this._onOverlayBlurHandler, o);
+
+                    if (!bDestroyed) {
+                        Event.removeListener(o.element, this.cfg.getProperty("focusevent"), this._onOverlayElementFocus);
+                        o.cfg.setProperty("zIndex", originalZ, true);
+                        o.cfg.setProperty("manager", null);
+                    }
+
+                    /* _managed Flag for custom or existing. Don't want to remove existing */
+                    if (o.focusEvent._managed) { o.focusEvent = null; }
+                    if (o.blurEvent._managed) { o.blurEvent = null; }
+
+                    if (o.focus._managed) { o.focus = null; }
+                    if (o.blur._managed) { o.blur = null; }
+                }
+            };
+
+            /**
+            * Removes focus from all registered Overlays in the manager
+            * @method blurAll
+            */
+            this.blurAll = function () {
+
+                var nOverlays = this.overlays.length,
+                    i;
+
+                if (nOverlays > 0) {
+                    i = nOverlays - 1;
+                    do {
+                        this.overlays[i].blur();
+                    }
+                    while(i--);
+                }
+            };
+
+            /**
+             * Updates the state of the OverlayManager and overlay, as a result of the overlay
+             * being blurred.
+             * 
+             * @method _manageBlur
+             * @param {Overlay} overlay The overlay instance which got blurred.
+             * @protected
+             */
+            this._manageBlur = function (overlay) {
+                var changed = false;
+                if (activeOverlay == overlay) {
+                    Dom.removeClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
+                    activeOverlay = null;
+                    changed = true;
+                }
+                return changed;
+            };
+
+            /**
+             * Updates the state of the OverlayManager and overlay, as a result of the overlay 
+             * receiving focus.
+             *
+             * @method _manageFocus
+             * @param {Overlay} overlay The overlay instance which got focus.
+             * @protected
+             */
+            this._manageFocus = function(overlay) {
+                var changed = false;
+                if (activeOverlay != overlay) {
+                    if (activeOverlay) {
+                        activeOverlay.blur();
+                    }
+                    activeOverlay = overlay;
+                    this.bringToTop(activeOverlay);
+                    Dom.addClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
+                    changed = true;
+                }
+                return changed;
+            };
+
+            var overlays = this.cfg.getProperty("overlays");
+
+            if (! this.overlays) {
+                this.overlays = [];
+            }
+
+            if (overlays) {
+                this.register(overlays);
+                this.overlays.sort(this.compareZIndexDesc);
+            }
+        },
+
+        /**
+        * @method _onOverlayElementFocus
+        * @description Event handler for the DOM event that is used to focus 
+        * the Overlay instance as specified by the "focusevent" 
+        * configuration property.
+        * @private
+        * @param {Event} p_oEvent Object representing the DOM event 
+        * object passed back by the event utility (Event).
+        */
+        _onOverlayElementFocus: function (p_oEvent) {
+
+            var oTarget = Event.getTarget(p_oEvent),
+                oClose = this.close;
+
+            if (oClose && (oTarget == oClose || Dom.isAncestor(oClose, oTarget))) {
+                this.blur();
+            } else {
+                this.focus();
+            }
+        },
+
+        /**
+        * @method _onOverlayDestroy
+        * @description "destroy" event handler for the Overlay.
+        * @private
+        * @param {String} p_sType String representing the name of the event  
+        * that was fired.
+        * @param {Array} p_aArgs Array of arguments sent when the event 
+        * was fired.
+        * @param {Overlay} p_oOverlay Object representing the overlay that 
+        * fired the event.
+        */
+        _onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
+            this.remove(p_oOverlay);
+        },
+
+        /**
+        * @method _onOverlayFocusHandler
+        *
+        * focusEvent Handler, used to delegate to _manageFocus with the 
+        * correct arguments.
+        *
+        * @private
+        * @param {String} p_sType String representing the name of the event  
+        * that was fired.
+        * @param {Array} p_aArgs Array of arguments sent when the event 
+        * was fired.
+        * @param {Overlay} p_oOverlay Object representing the overlay that 
+        * fired the event.
+        */
+        _onOverlayFocusHandler: function(p_sType, p_aArgs, p_oOverlay) {
+            this._manageFocus(p_oOverlay);
+        },
+
+        /**
+        * @method _onOverlayBlurHandler
+        *
+        * blurEvent Handler, used to delegate to _manageBlur with the 
+        * correct arguments.
+        *
+        * @private
+        * @param {String} p_sType String representing the name of the event  
+        * that was fired.
+        * @param {Array} p_aArgs Array of arguments sent when the event 
+        * was fired.
+        * @param {Overlay} p_oOverlay Object representing the overlay that 
+        * fired the event.
+        */
+        _onOverlayBlurHandler: function(p_sType, p_aArgs, p_oOverlay) {
+            this._manageBlur(p_oOverlay);
+        },
+
+        /**
+         * Subscribes to the Overlay based instance focusEvent, to allow the OverlayManager to
+         * monitor focus state.
+         * 
+         * If the instance already has a focusEvent (e.g. Menu), OverlayManager will subscribe 
+         * to the existing focusEvent, however if a focusEvent or focus method does not exist
+         * on the instance, the _bindFocus method will add them, and the focus method will 
+         * update the OverlayManager's state directly.
+         * 
+         * @method _bindFocus
+         * @param {Overlay} overlay The overlay for which focus needs to be managed
+         * @protected
+         */
+        _bindFocus : function(overlay) {
+            var mgr = this;
+
+            if (!overlay.focusEvent) {
+                overlay.focusEvent = overlay.createEvent("focus");
+                overlay.focusEvent.signature = CustomEvent.LIST;
+                overlay.focusEvent._managed = true;
+            } else {
+                overlay.focusEvent.subscribe(mgr._onOverlayFocusHandler, overlay, mgr);
+            }
+
+            if (!overlay.focus) {
+                Event.on(overlay.element, mgr.cfg.getProperty("focusevent"), mgr._onOverlayElementFocus, null, overlay);
+                overlay.focus = function () {
+                    if (mgr._manageFocus(this)) {
+                        // For Panel/Dialog
+                        if (this.cfg.getProperty("visible") && this.focusFirst) {
+                            this.focusFirst();
+                        }
+                        this.focusEvent.fire();
+                    }
+                };
+                overlay.focus._managed = true;
+            }
+        },
+
+        /**
+         * Subscribes to the Overlay based instance's blurEvent to allow the OverlayManager to
+         * monitor blur state.
+         *
+         * If the instance already has a blurEvent (e.g. Menu), OverlayManager will subscribe 
+         * to the existing blurEvent, however if a blurEvent or blur method does not exist
+         * on the instance, the _bindBlur method will add them, and the blur method 
+         * update the OverlayManager's state directly.
+         *
+         * @method _bindBlur
+         * @param {Overlay} overlay The overlay for which blur needs to be managed
+         * @protected
+         */
+        _bindBlur : function(overlay) {
+            var mgr = this;
+
+            if (!overlay.blurEvent) {
+                overlay.blurEvent = overlay.createEvent("blur");
+                overlay.blurEvent.signature = CustomEvent.LIST;
+                overlay.focusEvent._managed = true;
+            } else {
+                overlay.blurEvent.subscribe(mgr._onOverlayBlurHandler, overlay, mgr);
+            }
+
+            if (!overlay.blur) {
+                overlay.blur = function () {
+                    if (mgr._manageBlur(this)) {
+                        this.blurEvent.fire();
+                    }
+                };
+                overlay.blur._managed = true;
+            }
+
+            overlay.hideEvent.subscribe(overlay.blur);
+        },
+
+        /**
+         * Subscribes to the Overlay based instance's destroyEvent, to allow the Overlay
+         * to be removed for the OverlayManager when destroyed.
+         * 
+         * @method _bindDestroy
+         * @param {Overlay} overlay The overlay instance being managed
+         * @protected
+         */
+        _bindDestroy : function(overlay) {
+            var mgr = this;
+            overlay.destroyEvent.subscribe(mgr._onOverlayDestroy, overlay, mgr);
+        },
+
+        /**
+         * Ensures the zIndex configuration property on the managed overlay based instance
+         * is set to the computed zIndex value from the DOM (with "auto" translating to 0).
+         *
+         * @method _syncZIndex
+         * @param {Overlay} overlay The overlay instance being managed
+         * @protected
+         */
+        _syncZIndex : function(overlay) {
+            var zIndex = Dom.getStyle(overlay.element, "zIndex");
+            if (!isNaN(zIndex)) {
+                overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
+            } else {
+                overlay.cfg.setProperty("zIndex", 0);
+            }
+        },
+
+        /**
+        * Registers an Overlay or an array of Overlays with the manager. Upon 
+        * registration, the Overlay receives functions for focus and blur, 
+        * along with CustomEvents for each.
+        *
+        * @method register
+        * @param {Overlay} overlay  An Overlay to register with the manager.
+        * @param {Overlay[]} overlay  An array of Overlays to register with 
+        * the manager.
+        * @return {boolean} true if any Overlays are registered.
+        */
+        register: function (overlay) {
+
+            var registered = false,
+                i,
+                n;
+
+            if (overlay instanceof Overlay) {
+
+                overlay.cfg.addProperty("manager", { value: this } );
+
+                this._bindFocus(overlay);
+                this._bindBlur(overlay);
+                this._bindDestroy(overlay);
+                this._syncZIndex(overlay);
+
+                this.overlays.push(overlay);
+                this.bringToTop(overlay);
+
+                registered = true;
+
+            } else if (overlay instanceof Array) {
+
+                for (i = 0, n = overlay.length; i < n; i++) {
+                    registered = this.register(overlay[i]) || registered;
+                }
+
+            }
+
+            return registered;
+        },
+
+        /**
+        * Places the specified Overlay instance on top of all other 
+        * Overlay instances.
+        * @method bringToTop
+        * @param {YAHOO.widget.Overlay} p_oOverlay Object representing an 
+        * Overlay instance.
+        * @param {String} p_oOverlay String representing the id of an 
+        * Overlay instance.
+        */        
+        bringToTop: function (p_oOverlay) {
+
+            var oOverlay = this.find(p_oOverlay),
+                nTopZIndex,
+                oTopOverlay,
+                aOverlays;
+
+            if (oOverlay) {
+
+                aOverlays = this.overlays;
+                aOverlays.sort(this.compareZIndexDesc);
+
+                oTopOverlay = aOverlays[0];
+
+                if (oTopOverlay) {
+                    nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
+
+                    if (!isNaN(nTopZIndex)) {
+
+                        var bRequiresBump = false;
+
+                        if (oTopOverlay !== oOverlay) {
+                            bRequiresBump = true;
+                        } else if (aOverlays.length > 1) {
+                            var nNextZIndex = Dom.getStyle(aOverlays[1].element, "zIndex");
+                            // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
+                            if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
+                                bRequiresBump = true;
+                            }
+                        }
+
+                        if (bRequiresBump) {
+                            oOverlay.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
+                        }
+                    }
+                    aOverlays.sort(this.compareZIndexDesc);
+                }
+            }
+        },
+
+        /**
+        * Attempts to locate an Overlay by instance or ID.
+        * @method find
+        * @param {Overlay} overlay  An Overlay to locate within the manager
+        * @param {String} overlay  An Overlay id to locate within the manager
+        * @return {Overlay} The requested Overlay, if found, or null if it 
+        * cannot be located.
+        */
+        find: function (overlay) {
+
+            var isInstance = overlay instanceof Overlay,
+                overlays = this.overlays,
+                n = overlays.length,
+                found = null,
+                o,
+                i;
+
+            if (isInstance || typeof overlay == "string") {
+                for (i = n-1; i >= 0; i--) {
+                    o = overlays[i];
+                    if ((isInstance && (o === overlay)) || (o.id == overlay)) {
+                        found = o;
+                        break;
+                    }
+                }
+            }
+
+            return found;
+        },
+
+        /**
+        * Used for sorting the manager's Overlays by z-index.
+        * @method compareZIndexDesc
+        * @private
+        * @return {Number} 0, 1, or -1, depending on where the Overlay should 
+        * fall in the stacking order.
+        */
+        compareZIndexDesc: function (o1, o2) {
+
+            var zIndex1 = (o1.cfg) ? o1.cfg.getProperty("zIndex") : null, // Sort invalid (destroyed)
+                zIndex2 = (o2.cfg) ? o2.cfg.getProperty("zIndex") : null; // objects at bottom.
+
+            if (zIndex1 === null && zIndex2 === null) {
+                return 0;
+            } else if (zIndex1 === null){
+                return 1;
+            } else if (zIndex2 === null) {
+                return -1;
+            } else if (zIndex1 > zIndex2) {
+                return -1;
+            } else if (zIndex1 < zIndex2) {
+                return 1;
+            } else {
+                return 0;
+            }
+        },
+
+        /**
+        * Shows all Overlays in the manager.
+        * @method showAll
+        */
+        showAll: function () {
+            var overlays = this.overlays,
+                n = overlays.length,
+                i;
+
+            for (i = n - 1; i >= 0; i--) {
+                overlays[i].show();
+            }
+        },
+
+        /**
+        * Hides all Overlays in the manager.
+        * @method hideAll
+        */
+        hideAll: function () {
+            var overlays = this.overlays,
+                n = overlays.length,
+                i;
+
+            for (i = n - 1; i >= 0; i--) {
+                overlays[i].hide();
+            }
+        },
+
+        /**
+        * Returns a string representation of the object.
+        * @method toString
+        * @return {String} The string representation of the OverlayManager
+        */
+        toString: function () {
+            return "OverlayManager";
+        }
+    };
+}());
+
+(function () {
+
+    /**
+    * Tooltip is an implementation of Overlay that behaves like an OS tooltip, 
+    * displaying when the user mouses over a particular element, and 
+    * disappearing on mouse out.
+    * @namespace YAHOO.widget
+    * @class Tooltip
+    * @extends YAHOO.widget.Overlay
+    * @constructor
+    * @param {String} el The element ID representing the Tooltip <em>OR</em>
+    * @param {HTMLElement} el The element representing the Tooltip
+    * @param {Object} userConfig The configuration object literal containing 
+    * the configuration that should be set for this Overlay. See configuration 
+    * documentation for more details.
+    */
+    YAHOO.widget.Tooltip = function (el, userConfig) {
+        YAHOO.widget.Tooltip.superclass.constructor.call(this, el, userConfig);
+    };
+
+    var Lang = YAHOO.lang,
+        Event = YAHOO.util.Event,
+        CustomEvent = YAHOO.util.CustomEvent,
+        Dom = YAHOO.util.Dom,
+        Tooltip = YAHOO.widget.Tooltip,
+        UA = YAHOO.env.ua,
+        bIEQuirks = (UA.ie && (UA.ie <= 6 || document.compatMode == "BackCompat")),
+
+        m_oShadowTemplate,
+
+        /**
+        * Constant representing the Tooltip's configuration properties
+        * @property DEFAULT_CONFIG
+        * @private
+        * @final
+        * @type Object
+        */
+        DEFAULT_CONFIG = {
+
+            "PREVENT_OVERLAP": { 
+                key: "preventoverlap", 
+                value: true, 
+                validator: Lang.isBoolean, 
+                supercedes: ["x", "y", "xy"] 
+            },
+
+            "SHOW_DELAY": { 
+                key: "showdelay", 
+                value: 200, 
+                validator: Lang.isNumber 
+            }, 
+
+            "AUTO_DISMISS_DELAY": { 
+                key: "autodismissdelay", 
+                value: 5000, 
+                validator: Lang.isNumber 
+            }, 
+
+            "HIDE_DELAY": { 
+                key: "hidedelay", 
+                value: 250, 
+                validator: Lang.isNumber 
+            }, 
+
+            "TEXT": { 
+                key: "text", 
+                suppressEvent: true 
+            }, 
+
+            "CONTAINER": { 
+                key: "container"
+            },
+
+            "DISABLED": {
+                key: "disabled",
+                value: false,
+                suppressEvent: true
+            }
+        },
+
+        /**
+        * Constant representing the name of the Tooltip's events
+        * @property EVENT_TYPES
+        * @private
+        * @final
+        * @type Object
+        */
+        EVENT_TYPES = {
+            "CONTEXT_MOUSE_OVER": "contextMouseOver",
+            "CONTEXT_MOUSE_OUT": "contextMouseOut",
+            "CONTEXT_TRIGGER": "contextTrigger"
+        };
+
+    /**
+    * Constant representing the Tooltip CSS class
+    * @property YAHOO.widget.Tooltip.CSS_TOOLTIP
+    * @static
+    * @final
+    * @type String
+    */
+    Tooltip.CSS_TOOLTIP = "yui-tt";
+
+    function restoreOriginalWidth(sOriginalWidth, sForcedWidth) {
+
+        var oConfig = this.cfg,
+            sCurrentWidth = oConfig.getProperty("width");
+
+        if (sCurrentWidth == sForcedWidth) {
+            oConfig.setProperty("width", sOriginalWidth);
+        }
+    }
+
+    /* 
+        changeContent event handler that sets a Tooltip instance's "width"
+        configuration property to the value of its root HTML 
+        elements's offsetWidth if a specific width has not been set.
+    */
+
+    function setWidthToOffsetWidth(p_sType, p_aArgs) {
+
+        if ("_originalWidth" in this) {
+            restoreOriginalWidth.call(this, this._originalWidth, this._forcedWidth);
+        }
+
+        var oBody = document.body,
+            oConfig = this.cfg,
+            sOriginalWidth = oConfig.getProperty("width"),
+            sNewWidth,
+            oClone;
+
+        if ((!sOriginalWidth || sOriginalWidth == "auto") && 
+            (oConfig.getProperty("container") != oBody || 
+            oConfig.getProperty("x") >= Dom.getViewportWidth() || 
+            oConfig.getProperty("y") >= Dom.getViewportHeight())) {
+
+            oClone = this.element.cloneNode(true);
+            oClone.style.visibility = "hidden";
+            oClone.style.top = "0px";
+            oClone.style.left = "0px";
+
+            oBody.appendChild(oClone);
+
+            sNewWidth = (oClone.offsetWidth + "px");
+
+            oBody.removeChild(oClone);
+            oClone = null;
+
+            oConfig.setProperty("width", sNewWidth);
+            oConfig.refireEvent("xy");
+
+            this._originalWidth = sOriginalWidth || "";
+            this._forcedWidth = sNewWidth;
+        }
+    }
+
+    // "onDOMReady" that renders the ToolTip
+
+    function onDOMReady(p_sType, p_aArgs, p_oObject) {
+        this.render(p_oObject);
+    }
+
+    //  "init" event handler that automatically renders the Tooltip
+
+    function onInit() {
+        Event.onDOMReady(onDOMReady, this.cfg.getProperty("container"), this);
+    }
+
+    YAHOO.extend(Tooltip, YAHOO.widget.Overlay, { 
+
+        /**
+        * The Tooltip initialization method. This method is automatically 
+        * called by the constructor. A Tooltip is automatically rendered by 
+        * the init method, and it also is set to be invisible by default, 
+        * and constrained to viewport by default as well.
+        * @method init
+        * @param {String} el The element ID representing the Tooltip <em>OR</em>
+        * @param {HTMLElement} el The element representing the Tooltip
+        * @param {Object} userConfig The configuration object literal 
+        * containing the configuration that should be set for this Tooltip. 
+        * See configuration documentation for more details.
+        */
+        init: function (el, userConfig) {
+
+
+            Tooltip.superclass.init.call(this, el);
+
+            this.beforeInitEvent.fire(Tooltip);
+
+            Dom.addClass(this.element, Tooltip.CSS_TOOLTIP);
+
+            if (userConfig) {
+                this.cfg.applyConfig(userConfig, true);
+            }
+
+            this.cfg.queueProperty("visible", false);
+            this.cfg.queueProperty("constraintoviewport", true);
+
+            this.setBody("");
+
+            this.subscribe("changeContent", setWidthToOffsetWidth);
+            this.subscribe("init", onInit);
+            this.subscribe("render", this.onRender);
+
+            this.initEvent.fire(Tooltip);
+        },
+
+        /**
+        * Initializes the custom events for Tooltip
+        * @method initEvents
+        */
+        initEvents: function () {
+
+            Tooltip.superclass.initEvents.call(this);
+            var SIGNATURE = CustomEvent.LIST;
+
+            /**
+            * CustomEvent fired when user mouses over a context element. Returning false from
+            * a subscriber to this event will prevent the tooltip from being displayed for
+            * the current context element.
+            * 
+            * @event contextMouseOverEvent
+            * @param {HTMLElement} context The context element which the user just moused over
+            * @param {DOMEvent} e The DOM event object, associated with the mouse over
+            */
+            this.contextMouseOverEvent = this.createEvent(EVENT_TYPES.CONTEXT_MOUSE_OVER);
+            this.contextMouseOverEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired when the user mouses out of a context element.
+            * 
+            * @event contextMouseOutEvent
+            * @param {HTMLElement} context The context element which the user just moused out of
+            * @param {DOMEvent} e The DOM event object, associated with the mouse out
+            */
+            this.contextMouseOutEvent = this.createEvent(EVENT_TYPES.CONTEXT_MOUSE_OUT);
+            this.contextMouseOutEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired just before the tooltip is displayed for the current context.
+            * <p>
+            *  You can subscribe to this event if you need to set up the text for the 
+            *  tooltip based on the context element for which it is about to be displayed.
+            * </p>
+            * <p>This event differs from the beforeShow event in following respects:</p>
+            * <ol>
+            *   <li>
+            *    When moving from one context element to another, if the tooltip is not
+            *    hidden (the <code>hidedelay</code> is not reached), the beforeShow and Show events will not
+            *    be fired when the tooltip is displayed for the new context since it is already visible.
+            *    However the contextTrigger event is always fired before displaying the tooltip for
+            *    a new context.
+            *   </li>
+            *   <li>
+            *    The trigger event provides access to the context element, allowing you to 
+            *    set the text of the tooltip based on context element for which the tooltip is
+            *    triggered.
+            *   </li>
+            * </ol>
+            * <p>
+            *  It is not possible to prevent the tooltip from being displayed
+            *  using this event. You can use the contextMouseOverEvent if you need to prevent
+            *  the tooltip from being displayed.
+            * </p>
+            * @event contextTriggerEvent
+            * @param {HTMLElement} context The context element for which the tooltip is triggered
+            */
+            this.contextTriggerEvent = this.createEvent(EVENT_TYPES.CONTEXT_TRIGGER);
+            this.contextTriggerEvent.signature = SIGNATURE;
+        },
+
+        /**
+        * Initializes the class's configurable properties which can be 
+        * changed using the Overlay's Config object (cfg).
+        * @method initDefaultConfig
+        */
+        initDefaultConfig: function () {
+
+            Tooltip.superclass.initDefaultConfig.call(this);
+
+            /**
+            * Specifies whether the Tooltip should be kept from overlapping 
+            * its context element.
+            * @config preventoverlap
+            * @type Boolean
+            * @default true
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.PREVENT_OVERLAP.key, {
+                value: DEFAULT_CONFIG.PREVENT_OVERLAP.value, 
+                validator: DEFAULT_CONFIG.PREVENT_OVERLAP.validator, 
+                supercedes: DEFAULT_CONFIG.PREVENT_OVERLAP.supercedes
+            });
+
+            /**
+            * The number of milliseconds to wait before showing a Tooltip 
+            * on mouseover.
+            * @config showdelay
+            * @type Number
+            * @default 200
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.SHOW_DELAY.key, {
+                handler: this.configShowDelay,
+                value: 200, 
+                validator: DEFAULT_CONFIG.SHOW_DELAY.validator
+            });
+
+            /**
+            * The number of milliseconds to wait before automatically 
+            * dismissing a Tooltip after the mouse has been resting on the 
+            * context element.
+            * @config autodismissdelay
+            * @type Number
+            * @default 5000
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.AUTO_DISMISS_DELAY.key, {
+                handler: this.configAutoDismissDelay,
+                value: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.value,
+                validator: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.validator
+            });
+
+            /**
+            * The number of milliseconds to wait before hiding a Tooltip 
+            * after mouseout.
+            * @config hidedelay
+            * @type Number
+            * @default 250
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.HIDE_DELAY.key, {
+                handler: this.configHideDelay,
+                value: DEFAULT_CONFIG.HIDE_DELAY.value, 
+                validator: DEFAULT_CONFIG.HIDE_DELAY.validator
+            });
+
+            /**
+            * Specifies the Tooltip's text. 
+            * @config text
+            * @type String
+            * @default null
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, {
+                handler: this.configText,
+                suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent
+            });
+
+            /**
+            * Specifies the container element that the Tooltip's markup 
+            * should be rendered into.
+            * @config container
+            * @type HTMLElement/String
+            * @default document.body
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.CONTAINER.key, {
+                handler: this.configContainer,
+                value: document.body
+            });
+
+            /**
+            * Specifies whether or not the tooltip is disabled. Disabled tooltips
+            * will not be displayed. If the tooltip is driven by the title attribute
+            * of the context element, the title attribute will still be removed for 
+            * disabled tooltips, to prevent default tooltip behavior.
+            * 
+            * @config disabled
+            * @type Boolean
+            * @default false
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.DISABLED.key, {
+                handler: this.configContainer,
+                value: DEFAULT_CONFIG.DISABLED.value,
+                supressEvent: DEFAULT_CONFIG.DISABLED.suppressEvent
+            });
+
+            /**
+            * Specifies the element or elements that the Tooltip should be 
+            * anchored to on mouseover.
+            * @config context
+            * @type HTMLElement[]/String[]
+            * @default null
+            */ 
+
+            /**
+            * String representing the width of the Tooltip.  <em>Please note:
+            * </em> As of version 2.3 if either no value or a value of "auto" 
+            * is specified, and the Toolip's "container" configuration property
+            * is set to something other than <code>document.body</code> or 
+            * its "context" element resides outside the immediately visible 
+            * portion of the document, the width of the Tooltip will be 
+            * calculated based on the offsetWidth of its root HTML and set just 
+            * before it is made visible.  The original value will be 
+            * restored when the Tooltip is hidden. This ensures the Tooltip is 
+            * rendered at a usable width.  For more information see 
+            * SourceForge bug #1685496 and SourceForge 
+            * bug #1735423.
+            * @config width
+            * @type String
+            * @default null
+            */
+        
+        },
+        
+        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
+        
+        /**
+        * The default event handler fired when the "text" property is changed.
+        * @method configText
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configText: function (type, args, obj) {
+            var text = args[0];
+            if (text) {
+                this.setBody(text);
+            }
+        },
+        
+        /**
+        * The default event handler fired when the "container" property 
+        * is changed.
+        * @method configContainer
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For 
+        * configuration handlers, args[0] will equal the newly applied value 
+        * for the property.
+        * @param {Object} obj The scope object. For configuration handlers,
+        * this will usually equal the owner.
+        */
+        configContainer: function (type, args, obj) {
+            var container = args[0];
+
+            if (typeof container == 'string') {
+                this.cfg.setProperty("container", document.getElementById(container), true);
+            }
+        },
+        
+        /**
+        * @method _removeEventListeners
+        * @description Removes all of the DOM event handlers from the HTML
+        *  element(s) that trigger the display of the tooltip.
+        * @protected
+        */
+        _removeEventListeners: function () {
+        
+            var aElements = this._context,
+                nElements,
+                oElement,
+                i;
+
+            if (aElements) {
+                nElements = aElements.length;
+                if (nElements > 0) {
+                    i = nElements - 1;
+                    do {
+                        oElement = aElements[i];
+                        Event.removeListener(oElement, "mouseover", this.onContextMouseOver);
+                        Event.removeListener(oElement, "mousemove", this.onContextMouseMove);
+                        Event.removeListener(oElement, "mouseout", this.onContextMouseOut);
+                    }
+                    while (i--);
+                }
+            }
+        },
+        
+        /**
+        * The default event handler fired when the "context" property 
+        * is changed.
+        * @method configContext
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers,
+        * this will usually equal the owner.
+        */
+        configContext: function (type, args, obj) {
+
+            var context = args[0],
+                aElements,
+                nElements,
+                oElement,
+                i;
+
+            if (context) {
+
+                // Normalize parameter into an array
+                if (! (context instanceof Array)) {
+                    if (typeof context == "string") {
+                        this.cfg.setProperty("context", [document.getElementById(context)], true);
+                    } else { // Assuming this is an element
+                        this.cfg.setProperty("context", [context], true);
+                    }
+                    context = this.cfg.getProperty("context");
+                }
+
+                // Remove any existing mouseover/mouseout listeners
+                this._removeEventListeners();
+
+                // Add mouseover/mouseout listeners to context elements
+                this._context = context;
+
+                aElements = this._context;
+
+                if (aElements) {
+                    nElements = aElements.length;
+                    if (nElements > 0) {
+                        i = nElements - 1;
+                        do {
+                            oElement = aElements[i];
+                            Event.on(oElement, "mouseover", this.onContextMouseOver, this);
+                            Event.on(oElement, "mousemove", this.onContextMouseMove, this);
+                            Event.on(oElement, "mouseout", this.onContextMouseOut, this);
+                        }
+                        while (i--);
+                    }
+                }
+            }
+        },
+
+        // END BUILT-IN PROPERTY EVENT HANDLERS //
+
+        // BEGIN BUILT-IN DOM EVENT HANDLERS //
+
+        /**
+        * The default event handler fired when the user moves the mouse while 
+        * over the context element.
+        * @method onContextMouseMove
+        * @param {DOMEvent} e The current DOM event
+        * @param {Object} obj The object argument
+        */
+        onContextMouseMove: function (e, obj) {
+            obj.pageX = Event.getPageX(e);
+            obj.pageY = Event.getPageY(e);
+        },
+
+        /**
+        * The default event handler fired when the user mouses over the 
+        * context element.
+        * @method onContextMouseOver
+        * @param {DOMEvent} e The current DOM event
+        * @param {Object} obj The object argument
+        */
+        onContextMouseOver: function (e, obj) {
+            var context = this;
+
+            if (context.title) {
+                obj._tempTitle = context.title;
+                context.title = "";
+            }
+
+            // Fire first, to honor disabled set in the listner
+            if (obj.fireEvent("contextMouseOver", context, e) !== false 
+                    && !obj.cfg.getProperty("disabled")) {
+
+                // Stop the tooltip from being hidden (set on last mouseout)
+                if (obj.hideProcId) {
+                    clearTimeout(obj.hideProcId);
+                    obj.hideProcId = null;
+                }
+
+                Event.on(context, "mousemove", obj.onContextMouseMove, obj);
+
+                /**
+                * The unique process ID associated with the thread responsible 
+                * for showing the Tooltip.
+                * @type int
+                */
+                obj.showProcId = obj.doShow(e, context);
+            }
+        },
+
+        /**
+        * The default event handler fired when the user mouses out of 
+        * the context element.
+        * @method onContextMouseOut
+        * @param {DOMEvent} e The current DOM event
+        * @param {Object} obj The object argument
+        */
+        onContextMouseOut: function (e, obj) {
+            var el = this;
+
+            if (obj._tempTitle) {
+                el.title = obj._tempTitle;
+                obj._tempTitle = null;
+            }
+
+            if (obj.showProcId) {
+                clearTimeout(obj.showProcId);
+                obj.showProcId = null;
+            }
+
+            if (obj.hideProcId) {
+                clearTimeout(obj.hideProcId);
+                obj.hideProcId = null;
+            }
+
+            obj.fireEvent("contextMouseOut", el, e);
+
+            obj.hideProcId = setTimeout(function () {
+                obj.hide();
+            }, obj.cfg.getProperty("hidedelay"));
+        },
+
+        // END BUILT-IN DOM EVENT HANDLERS //
+
+        /**
+        * Processes the showing of the Tooltip by setting the timeout delay 
+        * and offset of the Tooltip.
+        * @method doShow
+        * @param {DOMEvent} e The current DOM event
+        * @param {HTMLElement} context The current context element
+        * @return {Number} The process ID of the timeout function associated 
+        * with doShow
+        */
+        doShow: function (e, context) {
+
+            var yOffset = 25,
+                me = this;
+
+            if (UA.opera && context.tagName && 
+                context.tagName.toUpperCase() == "A") {
+                yOffset += 12;
+            }
+
+            return setTimeout(function () {
+
+                var txt = me.cfg.getProperty("text");
+
+                // title does not over-ride text
+                if (me._tempTitle && (txt === "" || YAHOO.lang.isUndefined(txt) || YAHOO.lang.isNull(txt))) {
+                    me.setBody(me._tempTitle);
+                } else {
+                    me.cfg.refireEvent("text");
+                }
+
+                me.moveTo(me.pageX, me.pageY + yOffset);
+
+                if (me.cfg.getProperty("preventoverlap")) {
+                    me.preventOverlap(me.pageX, me.pageY);
+                }
+
+                Event.removeListener(context, "mousemove", me.onContextMouseMove);
+
+                me.contextTriggerEvent.fire(context);
+
+                me.show();
+
+                me.hideProcId = me.doHide();
+
+            }, this.cfg.getProperty("showdelay"));
+        },
+
+        /**
+        * Sets the timeout for the auto-dismiss delay, which by default is 5 
+        * seconds, meaning that a tooltip will automatically dismiss itself 
+        * after 5 seconds of being displayed.
+        * @method doHide
+        */
+        doHide: function () {
+
+            var me = this;
+
+
+            return setTimeout(function () {
+
+                me.hide();
+
+            }, this.cfg.getProperty("autodismissdelay"));
+
+        },
+
+        /**
+        * Fired when the Tooltip is moved, this event handler is used to 
+        * prevent the Tooltip from overlapping with its context element.
+        * @method preventOverlay
+        * @param {Number} pageX The x coordinate position of the mouse pointer
+        * @param {Number} pageY The y coordinate position of the mouse pointer
+        */
+        preventOverlap: function (pageX, pageY) {
+        
+            var height = this.element.offsetHeight,
+                mousePoint = new YAHOO.util.Point(pageX, pageY),
+                elementRegion = Dom.getRegion(this.element);
+        
+            elementRegion.top -= 5;
+            elementRegion.left -= 5;
+            elementRegion.right += 5;
+            elementRegion.bottom += 5;
+        
+        
+            if (elementRegion.contains(mousePoint)) {
+                this.cfg.setProperty("y", (pageY - height - 5));
+            }
+        },
+
+
+        /**
+        * @method onRender
+        * @description "render" event handler for the Tooltip.
+        * @param {String} p_sType String representing the name of the event  
+        * that was fired.
+        * @param {Array} p_aArgs Array of arguments sent when the event 
+        * was fired.
+        */
+        onRender: function (p_sType, p_aArgs) {
+    
+            function sizeShadow() {
+    
+                var oElement = this.element,
+                    oShadow = this.underlay;
+            
+                if (oShadow) {
+                    oShadow.style.width = (oElement.offsetWidth + 6) + "px";
+                    oShadow.style.height = (oElement.offsetHeight + 1) + "px"; 
+                }
+            
+            }
+
+            function addShadowVisibleClass() {
+                Dom.addClass(this.underlay, "yui-tt-shadow-visible");
+
+                if (UA.ie) {
+                    this.forceUnderlayRedraw();
+                }
+            }
+
+            function removeShadowVisibleClass() {
+                Dom.removeClass(this.underlay, "yui-tt-shadow-visible");
+            }
+
+            function createShadow() {
+    
+                var oShadow = this.underlay,
+                    oElement,
+                    Module,
+                    nIE,
+                    me;
+    
+                if (!oShadow) {
+    
+                    oElement = this.element;
+                    Module = YAHOO.widget.Module;
+                    nIE = UA.ie;
+                    me = this;
+
+                    if (!m_oShadowTemplate) {
+                        m_oShadowTemplate = document.createElement("div");
+                        m_oShadowTemplate.className = "yui-tt-shadow";
+                    }
+
+                    oShadow = m_oShadowTemplate.cloneNode(false);
+
+                    oElement.appendChild(oShadow);
+
+                    this.underlay = oShadow;
+
+                    // Backward compatibility, even though it's probably 
+                    // intended to be "private", it isn't marked as such in the api docs
+                    this._shadow = this.underlay;
+
+                    addShadowVisibleClass.call(this);
+
+                    this.subscribe("beforeShow", addShadowVisibleClass);
+                    this.subscribe("hide", removeShadowVisibleClass);
+
+                    if (bIEQuirks) {
+                        window.setTimeout(function () { 
+                            sizeShadow.call(me); 
+                        }, 0);
+    
+                        this.cfg.subscribeToConfigEvent("width", sizeShadow);
+                        this.cfg.subscribeToConfigEvent("height", sizeShadow);
+                        this.subscribe("changeContent", sizeShadow);
+
+                        Module.textResizeEvent.subscribe(sizeShadow, this, true);
+                        this.subscribe("destroy", function () {
+                            Module.textResizeEvent.unsubscribe(sizeShadow, this);
+                        });
+                    }
+                }
+            }
+
+            function onBeforeShow() {
+                createShadow.call(this);
+                this.unsubscribe("beforeShow", onBeforeShow);
+            }
+
+            if (this.cfg.getProperty("visible")) {
+                createShadow.call(this);
+            } else {
+                this.subscribe("beforeShow", onBeforeShow);
+            }
+        
+        },
+
+        /**
+         * Forces the underlay element to be repainted, through the application/removal
+         * of a yui-force-redraw class to the underlay element.
+         * 
+         * @method forceUnderlayRedraw
+         */
+        forceUnderlayRedraw : function() {
+            var tt = this;
+            Dom.addClass(tt.underlay, "yui-force-redraw");
+            setTimeout(function() {Dom.removeClass(tt.underlay, "yui-force-redraw");}, 0);
+        },
+
+        /**
+        * Removes the Tooltip element from the DOM and sets all child 
+        * elements to null.
+        * @method destroy
+        */
+        destroy: function () {
+        
+            // Remove any existing mouseover/mouseout listeners
+            this._removeEventListeners();
+
+            Tooltip.superclass.destroy.call(this);  
+        
+        },
+        
+        /**
+        * Returns a string representation of the object.
+        * @method toString
+        * @return {String} The string representation of the Tooltip
+        */
+        toString: function () {
+            return "Tooltip " + this.id;
+        }
+    
+    });
+
+}());
+
+(function () {
+
+    /**
+    * Panel is an implementation of Overlay that behaves like an OS window, 
+    * with a draggable header and an optional close icon at the top right.
+    * @namespace YAHOO.widget
+    * @class Panel
+    * @extends YAHOO.widget.Overlay
+    * @constructor
+    * @param {String} el The element ID representing the Panel <em>OR</em>
+    * @param {HTMLElement} el The element representing the Panel
+    * @param {Object} userConfig The configuration object literal containing 
+    * the configuration that should be set for this Panel. See configuration 
+    * documentation for more details.
+    */
+    YAHOO.widget.Panel = function (el, userConfig) {
+        YAHOO.widget.Panel.superclass.constructor.call(this, el, userConfig);
+    };
+
+    var _currentModal = null;
+
+    var Lang = YAHOO.lang,
+        Util = YAHOO.util,
+        Dom = Util.Dom,
+        Event = Util.Event,
+        CustomEvent = Util.CustomEvent,
+        KeyListener = YAHOO.util.KeyListener,
+        Config = Util.Config,
+        Overlay = YAHOO.widget.Overlay,
+        Panel = YAHOO.widget.Panel,
+        UA = YAHOO.env.ua,
+
+        bIEQuirks = (UA.ie && (UA.ie <= 6 || document.compatMode == "BackCompat")),
+
+        m_oMaskTemplate,
+        m_oUnderlayTemplate,
+        m_oCloseIconTemplate,
+
+        /**
+        * Constant representing the name of the Panel's events
+        * @property EVENT_TYPES
+        * @private
+        * @final
+        * @type Object
+        */
+        EVENT_TYPES = {
+            "SHOW_MASK": "showMask",
+            "HIDE_MASK": "hideMask",
+            "DRAG": "drag"
+        },
+
+        /**
+        * Constant representing the Panel's configuration properties
+        * @property DEFAULT_CONFIG
+        * @private
+        * @final
+        * @type Object
+        */
+        DEFAULT_CONFIG = {
+
+            "CLOSE": { 
+                key: "close", 
+                value: true, 
+                validator: Lang.isBoolean, 
+                supercedes: ["visible"] 
+            },
+
+            "DRAGGABLE": {
+                key: "draggable", 
+                value: (Util.DD ? true : false), 
+                validator: Lang.isBoolean, 
+                supercedes: ["visible"]  
+            },
+
+            "DRAG_ONLY" : {
+                key: "dragonly",
+                value: false,
+                validator: Lang.isBoolean,
+                supercedes: ["draggable"]
+            },
+
+            "UNDERLAY": { 
+                key: "underlay", 
+                value: "shadow", 
+                supercedes: ["visible"] 
+            },
+
+            "MODAL": { 
+                key: "modal", 
+                value: false, 
+                validator: Lang.isBoolean, 
+                supercedes: ["visible", "zindex"]
+            },
+
+            "KEY_LISTENERS": {
+                key: "keylisteners",
+                suppressEvent: true,
+                supercedes: ["visible"]
+            },
+
+            "STRINGS" : {
+                key: "strings",
+                supercedes: ["close"],
+                validator: Lang.isObject,
+                value: {
+                    close: "Close"
+                }
+            }
+        };
+
+    /**
+    * Constant representing the default CSS class used for a Panel
+    * @property YAHOO.widget.Panel.CSS_PANEL
+    * @static
+    * @final
+    * @type String
+    */
+    Panel.CSS_PANEL = "yui-panel";
+    
+    /**
+    * Constant representing the default CSS class used for a Panel's 
+    * wrapping container
+    * @property YAHOO.widget.Panel.CSS_PANEL_CONTAINER
+    * @static
+    * @final
+    * @type String
+    */
+    Panel.CSS_PANEL_CONTAINER = "yui-panel-container";
+
+    /**
+     * Constant representing the default set of focusable elements 
+     * on the pagewhich Modal Panels will prevent access to, when
+     * the modal mask is displayed
+     * 
+     * @property YAHOO.widget.Panel.FOCUSABLE
+     * @static
+     * @type Array
+     */
+    Panel.FOCUSABLE = [
+        "a",
+        "button",
+        "select",
+        "textarea",
+        "input",
+        "iframe"
+    ];
+
+    // Private CustomEvent listeners
+
+    /* 
+        "beforeRender" event handler that creates an empty header for a Panel 
+        instance if its "draggable" configuration property is set to "true" 
+        and no header has been created.
+    */
+
+    function createHeader(p_sType, p_aArgs) {
+        if (!this.header && this.cfg.getProperty("draggable")) {
+            this.setHeader("&#160;");
+        }
+    }
+
+    /* 
+        "hide" event handler that sets a Panel instance's "width"
+        configuration property back to its original value before 
+        "setWidthToOffsetWidth" was called.
+    */
+    
+    function restoreOriginalWidth(p_sType, p_aArgs, p_oObject) {
+
+        var sOriginalWidth = p_oObject[0],
+            sNewWidth = p_oObject[1],
+            oConfig = this.cfg,
+            sCurrentWidth = oConfig.getProperty("width");
+
+        if (sCurrentWidth == sNewWidth) {
+            oConfig.setProperty("width", sOriginalWidth);
+        }
+
+        this.unsubscribe("hide", restoreOriginalWidth, p_oObject);
+    }
+
+    /* 
+        "beforeShow" event handler that sets a Panel instance's "width"
+        configuration property to the value of its root HTML 
+        elements's offsetWidth
+    */
+
+    function setWidthToOffsetWidth(p_sType, p_aArgs) {
+
+        var oConfig,
+            sOriginalWidth,
+            sNewWidth;
+
+        if (bIEQuirks) {
+
+            oConfig = this.cfg;
+            sOriginalWidth = oConfig.getProperty("width");
+            
+            if (!sOriginalWidth || sOriginalWidth == "auto") {
+    
+                sNewWidth = (this.element.offsetWidth + "px");
+    
+                oConfig.setProperty("width", sNewWidth);
+
+                this.subscribe("hide", restoreOriginalWidth, 
+                    [(sOriginalWidth || ""), sNewWidth]);
+            
+            }
+        }
+    }
+
+    YAHOO.extend(Panel, Overlay, {
+
+        /**
+        * The Overlay initialization method, which is executed for Overlay and 
+        * all of its subclasses. This method is automatically called by the 
+        * constructor, and  sets up all DOM references for pre-existing markup, 
+        * and creates required markup if it is not already present.
+        * @method init
+        * @param {String} el The element ID representing the Overlay <em>OR</em>
+        * @param {HTMLElement} el The element representing the Overlay
+        * @param {Object} userConfig The configuration object literal 
+        * containing the configuration that should be set for this Overlay. 
+        * See configuration documentation for more details.
+        */
+        init: function (el, userConfig) {
+            /*
+                 Note that we don't pass the user config in here yet because 
+                 we only want it executed once, at the lowest subclass level
+            */
+
+            Panel.superclass.init.call(this, el/*, userConfig*/);
+
+            this.beforeInitEvent.fire(Panel);
+
+            Dom.addClass(this.element, Panel.CSS_PANEL);
+
+            this.buildWrapper();
+
+            if (userConfig) {
+                this.cfg.applyConfig(userConfig, true);
+            }
+
+            this.subscribe("showMask", this._addFocusHandlers);
+            this.subscribe("hideMask", this._removeFocusHandlers);
+            this.subscribe("beforeRender", createHeader);
+
+            this.subscribe("render", function() {
+                this.setFirstLastFocusable();
+                this.subscribe("changeContent", this.setFirstLastFocusable);
+            });
+
+            this.subscribe("show", this.focusFirst);
+
+            this.initEvent.fire(Panel);
+        },
+
+        /**
+         * @method _onElementFocus
+         * @private
+         *
+         * "focus" event handler for a focuable element. Used to automatically
+         * blur the element when it receives focus to ensure that a Panel
+         * instance's modality is not compromised.
+         *
+         * @param {Event} e The DOM event object
+         */
+        _onElementFocus : function(e){
+
+            if(_currentModal === this) {
+
+                var target = Event.getTarget(e),
+                    doc = document.documentElement,
+                    insideDoc = (target !== doc && target !== window);
+
+                // mask and documentElement checks added for IE, which focuses on the mask when it's clicked on, and focuses on 
+                // the documentElement, when the document scrollbars are clicked on
+                if (insideDoc && target !== this.element && target !== this.mask && !Dom.isAncestor(this.element, target)) {
+                    try {
+                        if (this.firstElement) {
+                            this.firstElement.focus();
+                        } else {
+                            if (this._modalFocus) {
+                                this._modalFocus.focus();
+                            } else {
+                                this.innerElement.focus();
+                            }
+                        }
+                    } catch(err){
+                        // Just in case we fail to focus
+                        try {
+                            if (insideDoc && target !== document.body) {
+                                target.blur();
+                            }
+                        } catch(err2) { }
+                    }
+                }
+            }
+        },
+
+        /** 
+         *  @method _addFocusHandlers
+         *  @protected
+         *  
+         *  "showMask" event handler that adds a "focus" event handler to all
+         *  focusable elements in the document to enforce a Panel instance's 
+         *  modality from being compromised.
+         *
+         *  @param p_sType {String} Custom event type
+         *  @param p_aArgs {Array} Custom event arguments
+         */
+        _addFocusHandlers: function(p_sType, p_aArgs) {
+            if (!this.firstElement) {
+                if (UA.webkit || UA.opera) {
+                    if (!this._modalFocus) {
+                        this._createHiddenFocusElement();
+                    }
+                } else {
+                    this.innerElement.tabIndex = 0;
+                }
+            }
+            this.setTabLoop(this.firstElement, this.lastElement);
+            Event.onFocus(document.documentElement, this._onElementFocus, this, true);
+            _currentModal = this;
+        },
+
+        /**
+         * Creates a hidden focusable element, used to focus on,
+         * to enforce modality for browsers in which focus cannot
+         * be applied to the container box.
+         * 
+         * @method _createHiddenFocusElement
+         * @private
+         */
+        _createHiddenFocusElement : function() {
+            var e = document.createElement("button");
+            e.style.height = "1px";
+            e.style.width = "1px";
+            e.style.position = "absolute";
+            e.style.left = "-10000em";
+            e.style.opacity = 0;
+            e.tabIndex = -1;
+            this.innerElement.appendChild(e);
+            this._modalFocus = e;
+        },
+
+        /**
+         *  @method _removeFocusHandlers
+         *  @protected
+         *
+         *  "hideMask" event handler that removes all "focus" event handlers added 
+         *  by the "addFocusEventHandlers" method.
+         *
+         *  @param p_sType {String} Event type
+         *  @param p_aArgs {Array} Event Arguments
+         */
+        _removeFocusHandlers: function(p_sType, p_aArgs) {
+            Event.removeFocusListener(document.documentElement, this._onElementFocus, this);
+
+            if (_currentModal == this) {
+                _currentModal = null;
+            }
+        },
+
+        /**
+         * Sets focus to the first element in the Panel.
+         *
+         * @method focusFirst
+         */
+        focusFirst: function (type, args, obj) {
+            var el = this.firstElement;
+
+            if (args && args[1]) {
+                Event.stopEvent(args[1]);
+            }
+
+            if (el) {
+                try {
+                    el.focus();
+                } catch(err) {
+                    // Ignore
+                }
+            }
+        },
+
+        /**
+         * Sets focus to the last element in the Panel.
+         *
+         * @method focusLast
+         */
+        focusLast: function (type, args, obj) {
+            var el = this.lastElement;
+
+            if (args && args[1]) {
+                Event.stopEvent(args[1]);
+            }
+
+            if (el) {
+                try {
+                    el.focus();
+                } catch(err) {
+                    // Ignore
+                }
+            }
+        },
+
+        /**
+         * Sets up a tab, shift-tab loop between the first and last elements
+         * provided. NOTE: Sets up the preventBackTab and preventTabOut KeyListener
+         * instance properties, which are reset everytime this method is invoked.
+         *
+         * @method setTabLoop
+         * @param {HTMLElement} firstElement
+         * @param {HTMLElement} lastElement
+         *
+         */
+        setTabLoop : function(firstElement, lastElement) {
+
+            var backTab = this.preventBackTab, tab = this.preventTabOut,
+                showEvent = this.showEvent, hideEvent = this.hideEvent;
+
+            if (backTab) {
+                backTab.disable();
+                showEvent.unsubscribe(backTab.enable, backTab);
+                hideEvent.unsubscribe(backTab.disable, backTab);
+                backTab = this.preventBackTab = null;
+            }
+
+            if (tab) {
+                tab.disable();
+                showEvent.unsubscribe(tab.enable, tab);
+                hideEvent.unsubscribe(tab.disable,tab);
+                tab = this.preventTabOut = null;
+            }
+
+            if (firstElement) {
+                this.preventBackTab = new KeyListener(firstElement, 
+                    {shift:true, keys:9},
+                    {fn:this.focusLast, scope:this, correctScope:true}
+                );
+                backTab = this.preventBackTab;
+
+                showEvent.subscribe(backTab.enable, backTab, true);
+                hideEvent.subscribe(backTab.disable,backTab, true);
+            }
+
+            if (lastElement) {
+                this.preventTabOut = new KeyListener(lastElement, 
+                    {shift:false, keys:9}, 
+                    {fn:this.focusFirst, scope:this, correctScope:true}
+                );
+                tab = this.preventTabOut;
+
+                showEvent.subscribe(tab.enable, tab, true);
+                hideEvent.subscribe(tab.disable,tab, true);
+            }
+        },
+
+        /**
+         * Returns an array of the currently focusable items which reside within
+         * Panel. The set of focusable elements the method looks for are defined
+         * in the Panel.FOCUSABLE static property
+         *
+         * @method getFocusableElements
+         * @param {HTMLElement} root element to start from.
+         */
+        getFocusableElements : function(root) {
+
+            root = root || this.innerElement;
+
+            var focusable = {};
+            for (var i = 0; i < Panel.FOCUSABLE.length; i++) {
+                focusable[Panel.FOCUSABLE[i]] = true;
+            }
+
+            function isFocusable(el) {
+                if (el.focus && el.type !== "hidden" && !el.disabled && focusable[el.tagName.toLowerCase()]) {
+                    return true;
+                }
+                return false;
+            }
+
+            // Not looking by Tag, since we want elements in DOM order
+            return Dom.getElementsBy(isFocusable, null, root);
+        },
+
+        /**
+         * Sets the firstElement and lastElement instance properties
+         * to the first and last focusable elements in the Panel.
+         *
+         * @method setFirstLastFocusable
+         */
+        setFirstLastFocusable : function() {
+
+            this.firstElement = null;
+            this.lastElement = null;
+
+            var elements = this.getFocusableElements();
+            this.focusableElements = elements;
+
+            if (elements.length > 0) {
+                this.firstElement = elements[0];
+                this.lastElement = elements[elements.length - 1];
+            }
+
+            if (this.cfg.getProperty("modal")) {
+                this.setTabLoop(this.firstElement, this.lastElement);
+            }
+        },
+
+        /**
+         * Initializes the custom events for Module which are fired 
+         * automatically at appropriate times by the Module class.
+         */
+        initEvents: function () {
+            Panel.superclass.initEvents.call(this);
+
+            var SIGNATURE = CustomEvent.LIST;
+
+            /**
+            * CustomEvent fired after the modality mask is shown
+            * @event showMaskEvent
+            */
+            this.showMaskEvent = this.createEvent(EVENT_TYPES.SHOW_MASK);
+            this.showMaskEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired after the modality mask is hidden
+            * @event hideMaskEvent
+            */
+            this.hideMaskEvent = this.createEvent(EVENT_TYPES.HIDE_MASK);
+            this.hideMaskEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent when the Panel is dragged
+            * @event dragEvent
+            */
+            this.dragEvent = this.createEvent(EVENT_TYPES.DRAG);
+            this.dragEvent.signature = SIGNATURE;
+        },
+
+        /**
+         * Initializes the class's configurable properties which can be changed 
+         * using the Panel's Config object (cfg).
+         * @method initDefaultConfig
+         */
+        initDefaultConfig: function () {
+            Panel.superclass.initDefaultConfig.call(this);
+
+            // Add panel config properties //
+
+            /**
+            * True if the Panel should display a "close" button
+            * @config close
+            * @type Boolean
+            * @default true
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.CLOSE.key, { 
+                handler: this.configClose, 
+                value: DEFAULT_CONFIG.CLOSE.value, 
+                validator: DEFAULT_CONFIG.CLOSE.validator, 
+                supercedes: DEFAULT_CONFIG.CLOSE.supercedes 
+            });
+
+            /**
+            * Boolean specifying if the Panel should be draggable.  The default 
+            * value is "true" if the Drag and Drop utility is included, 
+            * otherwise it is "false." <strong>PLEASE NOTE:</strong> There is a 
+            * known issue in IE 6 (Strict Mode and Quirks Mode) and IE 7 
+            * (Quirks Mode) where Panels that either don't have a value set for 
+            * their "width" configuration property, or their "width" 
+            * configuration property is set to "auto" will only be draggable by
+            * placing the mouse on the text of the Panel's header element.
+            * To fix this bug, draggable Panels missing a value for their 
+            * "width" configuration property, or whose "width" configuration 
+            * property is set to "auto" will have it set to the value of 
+            * their root HTML element's offsetWidth before they are made 
+            * visible.  The calculated width is then removed when the Panel is   
+            * hidden. <em>This fix is only applied to draggable Panels in IE 6 
+            * (Strict Mode and Quirks Mode) and IE 7 (Quirks Mode)</em>. For 
+            * more information on this issue see:
+            * SourceForge bugs #1726972 and #1589210.
+            * @config draggable
+            * @type Boolean
+            * @default true
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.DRAGGABLE.key, {
+                handler: this.configDraggable,
+                value: (Util.DD) ? true : false,
+                validator: DEFAULT_CONFIG.DRAGGABLE.validator,
+                supercedes: DEFAULT_CONFIG.DRAGGABLE.supercedes
+            });
+
+            /**
+            * Boolean specifying if the draggable Panel should be drag only, not interacting with drop 
+            * targets on the page.
+            * <p>
+            * When set to true, draggable Panels will not check to see if they are over drop targets,
+            * or fire the DragDrop events required to support drop target interaction (onDragEnter, 
+            * onDragOver, onDragOut, onDragDrop etc.).
+            * If the Panel is not designed to be dropped on any target elements on the page, then this 
+            * flag can be set to true to improve performance.
+            * </p>
+            * <p>
+            * When set to false, all drop target related events will be fired.
+            * </p>
+            * <p>
+            * The property is set to false by default to maintain backwards compatibility but should be 
+            * set to true if drop target interaction is not required for the Panel, to improve performance.</p>
+            * 
+            * @config dragOnly
+            * @type Boolean
+            * @default false
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.DRAG_ONLY.key, { 
+                value: DEFAULT_CONFIG.DRAG_ONLY.value, 
+                validator: DEFAULT_CONFIG.DRAG_ONLY.validator, 
+                supercedes: DEFAULT_CONFIG.DRAG_ONLY.supercedes 
+            });
+
+            /**
+            * Sets the type of underlay to display for the Panel. Valid values 
+            * are "shadow," "matte," and "none".  <strong>PLEASE NOTE:</strong> 
+            * The creation of the underlay element is deferred until the Panel 
+            * is initially made visible.  For Gecko-based browsers on Mac
+            * OS X the underlay elment is always created as it is used as a 
+            * shim to prevent Aqua scrollbars below a Panel instance from poking 
+            * through it (See SourceForge bug #836476).
+            * @config underlay
+            * @type String
+            * @default shadow
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.UNDERLAY.key, { 
+                handler: this.configUnderlay, 
+                value: DEFAULT_CONFIG.UNDERLAY.value, 
+                supercedes: DEFAULT_CONFIG.UNDERLAY.supercedes 
+            });
+        
+            /**
+            * True if the Panel should be displayed in a modal fashion, 
+            * automatically creating a transparent mask over the document that
+            * will not be removed until the Panel is dismissed.
+            * @config modal
+            * @type Boolean
+            * @default false
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.MODAL.key, { 
+                handler: this.configModal, 
+                value: DEFAULT_CONFIG.MODAL.value,
+                validator: DEFAULT_CONFIG.MODAL.validator, 
+                supercedes: DEFAULT_CONFIG.MODAL.supercedes 
+            });
+
+            /**
+            * A KeyListener (or array of KeyListeners) that will be enabled 
+            * when the Panel is shown, and disabled when the Panel is hidden.
+            * @config keylisteners
+            * @type YAHOO.util.KeyListener[]
+            * @default null
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.KEY_LISTENERS.key, { 
+                handler: this.configKeyListeners, 
+                suppressEvent: DEFAULT_CONFIG.KEY_LISTENERS.suppressEvent, 
+                supercedes: DEFAULT_CONFIG.KEY_LISTENERS.supercedes 
+            });
+
+            /**
+            * UI Strings used by the Panel
+            * 
+            * @config strings
+            * @type Object
+            * @default An object literal with the properties shown below:
+            *     <dl>
+            *         <dt>close</dt><dd><em>String</em> : The string to use for the close icon. Defaults to "Close".</dd>
+            *     </dl>
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.STRINGS.key, { 
+                value:DEFAULT_CONFIG.STRINGS.value,
+                handler:this.configStrings,
+                validator:DEFAULT_CONFIG.STRINGS.validator,
+                supercedes:DEFAULT_CONFIG.STRINGS.supercedes
+            });
+        },
+
+        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
+        
+        /**
+        * The default event handler fired when the "close" property is changed.
+        * The method controls the appending or hiding of the close icon at the 
+        * top right of the Panel.
+        * @method configClose
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configClose: function (type, args, obj) {
+
+            var val = args[0],
+                oClose = this.close,
+                strings = this.cfg.getProperty("strings");
+
+            if (val) {
+                if (!oClose) {
+
+                    if (!m_oCloseIconTemplate) {
+                        m_oCloseIconTemplate = document.createElement("a");
+                        m_oCloseIconTemplate.className = "container-close";
+                        m_oCloseIconTemplate.href = "#";
+                    }
+
+                    oClose = m_oCloseIconTemplate.cloneNode(true);
+                    this.innerElement.appendChild(oClose);
+
+                    oClose.innerHTML = (strings && strings.close) ? strings.close : "&#160;";
+
+                    Event.on(oClose, "click", this._doClose, this, true);
+
+                    this.close = oClose;
+
+                } else {
+                    oClose.style.display = "block";
+                }
+
+            } else {
+                if (oClose) {
+                    oClose.style.display = "none";
+                }
+            }
+
+        },
+
+        /**
+         * Event handler for the close icon
+         * 
+         * @method _doClose
+         * @protected
+         * 
+         * @param {DOMEvent} e
+         */
+        _doClose : function (e) {
+            Event.preventDefault(e);
+            this.hide();
+        },
+
+        /**
+        * The default event handler fired when the "draggable" property 
+        * is changed.
+        * @method configDraggable
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configDraggable: function (type, args, obj) {
+            var val = args[0];
+
+            if (val) {
+                if (!Util.DD) {
+                    this.cfg.setProperty("draggable", false);
+                    return;
+                }
+
+                if (this.header) {
+                    Dom.setStyle(this.header, "cursor", "move");
+                    this.registerDragDrop();
+                }
+
+                this.subscribe("beforeShow", setWidthToOffsetWidth);
+
+            } else {
+
+                if (this.dd) {
+                    this.dd.unreg();
+                }
+
+                if (this.header) {
+                    Dom.setStyle(this.header,"cursor","auto");
+                }
+
+                this.unsubscribe("beforeShow", setWidthToOffsetWidth);
+            }
+        },
+      
+        /**
+        * The default event handler fired when the "underlay" property 
+        * is changed.
+        * @method configUnderlay
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configUnderlay: function (type, args, obj) {
+
+            var bMacGecko = (this.platform == "mac" && UA.gecko),
+                sUnderlay = args[0].toLowerCase(),
+                oUnderlay = this.underlay,
+                oElement = this.element;
+
+            function createUnderlay() {
+                var bNew = false;
+                if (!oUnderlay) { // create if not already in DOM
+
+                    if (!m_oUnderlayTemplate) {
+                        m_oUnderlayTemplate = document.createElement("div");
+                        m_oUnderlayTemplate.className = "underlay";
+                    }
+
+                    oUnderlay = m_oUnderlayTemplate.cloneNode(false);
+                    this.element.appendChild(oUnderlay);
+
+                    this.underlay = oUnderlay;
+
+                    if (bIEQuirks) {
+                        this.sizeUnderlay();
+                        this.cfg.subscribeToConfigEvent("width", this.sizeUnderlay);
+                        this.cfg.subscribeToConfigEvent("height", this.sizeUnderlay);
+
+                        this.changeContentEvent.subscribe(this.sizeUnderlay);
+                        YAHOO.widget.Module.textResizeEvent.subscribe(this.sizeUnderlay, this, true);
+                    }
+
+                    if (UA.webkit && UA.webkit < 420) {
+                        this.changeContentEvent.subscribe(this.forceUnderlayRedraw);
+                    }
+
+                    bNew = true;
+                }
+            }
+
+            function onBeforeShow() {
+                var bNew = createUnderlay.call(this);
+                if (!bNew && bIEQuirks) {
+                    this.sizeUnderlay();
+                }
+                this._underlayDeferred = false;
+                this.beforeShowEvent.unsubscribe(onBeforeShow);
+            }
+
+            function destroyUnderlay() {
+                if (this._underlayDeferred) {
+                    this.beforeShowEvent.unsubscribe(onBeforeShow);
+                    this._underlayDeferred = false;
+                }
+
+                if (oUnderlay) {
+                    this.cfg.unsubscribeFromConfigEvent("width", this.sizeUnderlay);
+                    this.cfg.unsubscribeFromConfigEvent("height",this.sizeUnderlay);
+                    this.changeContentEvent.unsubscribe(this.sizeUnderlay);
+                    this.changeContentEvent.unsubscribe(this.forceUnderlayRedraw);
+                    YAHOO.widget.Module.textResizeEvent.unsubscribe(this.sizeUnderlay, this, true);
+
+                    this.element.removeChild(oUnderlay);
+
+                    this.underlay = null;
+                }
+            }
+
+            switch (sUnderlay) {
+                case "shadow":
+                    Dom.removeClass(oElement, "matte");
+                    Dom.addClass(oElement, "shadow");
+                    break;
+                case "matte":
+                    if (!bMacGecko) {
+                        destroyUnderlay.call(this);
+                    }
+                    Dom.removeClass(oElement, "shadow");
+                    Dom.addClass(oElement, "matte");
+                    break;
+                default:
+                    if (!bMacGecko) {
+                        destroyUnderlay.call(this);
+                    }
+                    Dom.removeClass(oElement, "shadow");
+                    Dom.removeClass(oElement, "matte");
+                    break;
+            }
+
+            if ((sUnderlay == "shadow") || (bMacGecko && !oUnderlay)) {
+                if (this.cfg.getProperty("visible")) {
+                    var bNew = createUnderlay.call(this);
+                    if (!bNew && bIEQuirks) {
+                        this.sizeUnderlay();
+                    }
+                } else {
+                    if (!this._underlayDeferred) {
+                        this.beforeShowEvent.subscribe(onBeforeShow);
+                        this._underlayDeferred = true;
+                    }
+                }
+            }
+        },
+        
+        /**
+        * The default event handler fired when the "modal" property is 
+        * changed. This handler subscribes or unsubscribes to the show and hide
+        * events to handle the display or hide of the modality mask.
+        * @method configModal
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configModal: function (type, args, obj) {
+
+            var modal = args[0];
+            if (modal) {
+                if (!this._hasModalityEventListeners) {
+
+                    this.subscribe("beforeShow", this.buildMask);
+                    this.subscribe("beforeShow", this.bringToTop);
+                    this.subscribe("beforeShow", this.showMask);
+                    this.subscribe("hide", this.hideMask);
+
+                    Overlay.windowResizeEvent.subscribe(this.sizeMask, 
+                        this, true);
+
+                    this._hasModalityEventListeners = true;
+                }
+            } else {
+                if (this._hasModalityEventListeners) {
+
+                    if (this.cfg.getProperty("visible")) {
+                        this.hideMask();
+                        this.removeMask();
+                    }
+
+                    this.unsubscribe("beforeShow", this.buildMask);
+                    this.unsubscribe("beforeShow", this.bringToTop);
+                    this.unsubscribe("beforeShow", this.showMask);
+                    this.unsubscribe("hide", this.hideMask);
+
+                    Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
+
+                    this._hasModalityEventListeners = false;
+                }
+            }
+        },
+
+        /**
+        * Removes the modality mask.
+        * @method removeMask
+        */
+        removeMask: function () {
+
+            var oMask = this.mask,
+                oParentNode;
+
+            if (oMask) {
+                /*
+                    Hide the mask before destroying it to ensure that DOM
+                    event handlers on focusable elements get removed.
+                */
+                this.hideMask();
+
+                oParentNode = oMask.parentNode;
+                if (oParentNode) {
+                    oParentNode.removeChild(oMask);
+                }
+
+                this.mask = null;
+            }
+        },
+        
+        /**
+        * The default event handler fired when the "keylisteners" property 
+        * is changed.
+        * @method configKeyListeners
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configKeyListeners: function (type, args, obj) {
+
+            var listeners = args[0],
+                listener,
+                nListeners,
+                i;
+        
+            if (listeners) {
+
+                if (listeners instanceof Array) {
+
+                    nListeners = listeners.length;
+
+                    for (i = 0; i < nListeners; i++) {
+
+                        listener = listeners[i];
+        
+                        if (!Config.alreadySubscribed(this.showEvent, 
+                            listener.enable, listener)) {
+
+                            this.showEvent.subscribe(listener.enable, 
+                                listener, true);
+
+                        }
+
+                        if (!Config.alreadySubscribed(this.hideEvent, 
+                            listener.disable, listener)) {
+
+                            this.hideEvent.subscribe(listener.disable, 
+                                listener, true);
+
+                            this.destroyEvent.subscribe(listener.disable, 
+                                listener, true);
+                        }
+                    }
+
+                } else {
+
+                    if (!Config.alreadySubscribed(this.showEvent, 
+                        listeners.enable, listeners)) {
+
+                        this.showEvent.subscribe(listeners.enable, 
+                            listeners, true);
+                    }
+
+                    if (!Config.alreadySubscribed(this.hideEvent, 
+                        listeners.disable, listeners)) {
+
+                        this.hideEvent.subscribe(listeners.disable, 
+                            listeners, true);
+
+                        this.destroyEvent.subscribe(listeners.disable, 
+                            listeners, true);
+
+                    }
+
+                }
+
+            }
+
+        },
+
+        /**
+        * The default handler for the "strings" property
+        * @method configStrings
+        */
+        configStrings : function(type, args, obj) {
+            var val = Lang.merge(DEFAULT_CONFIG.STRINGS.value, args[0]);
+            this.cfg.setProperty(DEFAULT_CONFIG.STRINGS.key, val, true);
+        },
+
+        /**
+        * The default event handler fired when the "height" property is changed.
+        * @method configHeight
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configHeight: function (type, args, obj) {
+            var height = args[0],
+                el = this.innerElement;
+
+            Dom.setStyle(el, "height", height);
+            this.cfg.refireEvent("iframe");
+        },
+
+        /**
+         * The default custom event handler executed when the Panel's height is changed, 
+         * if the autofillheight property has been set.
+         *
+         * @method _autoFillOnHeightChange
+         * @protected
+         * @param {String} type The event type
+         * @param {Array} args The array of arguments passed to event subscribers
+         * @param {HTMLElement} el The header, body or footer element which is to be resized to fill
+         * out the containers height
+         */
+        _autoFillOnHeightChange : function(type, args, el) {
+            Panel.superclass._autoFillOnHeightChange.apply(this, arguments);
+            if (bIEQuirks) {
+                var panel = this;
+                setTimeout(function() {
+                    panel.sizeUnderlay();
+                },0);
+            }
+        },
+
+        /**
+        * The default event handler fired when the "width" property is changed.
+        * @method configWidth
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configWidth: function (type, args, obj) {
+    
+            var width = args[0],
+                el = this.innerElement;
+    
+            Dom.setStyle(el, "width", width);
+            this.cfg.refireEvent("iframe");
+    
+        },
+        
+        /**
+        * The default event handler fired when the "zIndex" property is changed.
+        * @method configzIndex
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configzIndex: function (type, args, obj) {
+            Panel.superclass.configzIndex.call(this, type, args, obj);
+
+            if (this.mask || this.cfg.getProperty("modal") === true) {
+                var panelZ = Dom.getStyle(this.element, "zIndex");
+                if (!panelZ || isNaN(panelZ)) {
+                    panelZ = 0;
+                }
+
+                if (panelZ === 0) {
+                    // Recursive call to configzindex (which should be stopped
+                    // from going further because panelZ should no longer === 0)
+                    this.cfg.setProperty("zIndex", 1);
+                } else {
+                    this.stackMask();
+                }
+            }
+        },
+
+        // END BUILT-IN PROPERTY EVENT HANDLERS //
+        /**
+        * Builds the wrapping container around the Panel that is used for 
+        * positioning the shadow and matte underlays. The container element is 
+        * assigned to a  local instance variable called container, and the 
+        * element is reinserted inside of it.
+        * @method buildWrapper
+        */
+        buildWrapper: function () {
+
+            var elementParent = this.element.parentNode,
+                originalElement = this.element,
+                wrapper = document.createElement("div");
+
+            wrapper.className = Panel.CSS_PANEL_CONTAINER;
+            wrapper.id = originalElement.id + "_c";
+
+            if (elementParent) {
+                elementParent.insertBefore(wrapper, originalElement);
+            }
+
+            wrapper.appendChild(originalElement);
+
+            this.element = wrapper;
+            this.innerElement = originalElement;
+
+            Dom.setStyle(this.innerElement, "visibility", "inherit");
+        },
+
+        /**
+        * Adjusts the size of the shadow based on the size of the element.
+        * @method sizeUnderlay
+        */
+        sizeUnderlay: function () {
+            var oUnderlay = this.underlay,
+                oElement;
+
+            if (oUnderlay) {
+                oElement = this.element;
+                oUnderlay.style.width = oElement.offsetWidth + "px";
+                oUnderlay.style.height = oElement.offsetHeight + "px";
+            }
+        },
+
+        /**
+        * Registers the Panel's header for drag & drop capability.
+        * @method registerDragDrop
+        */
+        registerDragDrop: function () {
+
+            var me = this;
+
+            if (this.header) {
+
+                if (!Util.DD) {
+                    return;
+                }
+
+                var bDragOnly = (this.cfg.getProperty("dragonly") === true);
+                this.dd = new Util.DD(this.element.id, this.id, {dragOnly: bDragOnly});
+
+                if (!this.header.id) {
+                    this.header.id = this.id + "_h";
+                }
+
+                this.dd.startDrag = function () {
+
+                    var offsetHeight,
+                        offsetWidth,
+                        viewPortWidth,
+                        viewPortHeight,
+                        scrollX,
+                        scrollY;
+
+                    if (YAHOO.env.ua.ie == 6) {
+                        Dom.addClass(me.element,"drag");
+                    }
+
+                    if (me.cfg.getProperty("constraintoviewport")) {
+
+                        var nViewportOffset = Overlay.VIEWPORT_OFFSET;
+
+                        offsetHeight = me.element.offsetHeight;
+                        offsetWidth = me.element.offsetWidth;
+
+                        viewPortWidth = Dom.getViewportWidth();
+                        viewPortHeight = Dom.getViewportHeight();
+
+                        scrollX = Dom.getDocumentScrollLeft();
+                        scrollY = Dom.getDocumentScrollTop();
+
+                        if (offsetHeight + nViewportOffset < viewPortHeight) {
+                            this.minY = scrollY + nViewportOffset;
+                            this.maxY = scrollY + viewPortHeight - offsetHeight - nViewportOffset;
+                        } else {
+                            this.minY = scrollY + nViewportOffset;
+                            this.maxY = scrollY + nViewportOffset;
+                        }
+
+                        if (offsetWidth + nViewportOffset < viewPortWidth) {
+                            this.minX = scrollX + nViewportOffset;
+                            this.maxX = scrollX + viewPortWidth - offsetWidth - nViewportOffset;
+                        } else {
+                            this.minX = scrollX + nViewportOffset;
+                            this.maxX = scrollX + nViewportOffset;
+                        }
+
+                        this.constrainX = true;
+                        this.constrainY = true;
+                    } else {
+                        this.constrainX = false;
+                        this.constrainY = false;
+                    }
+
+                    me.dragEvent.fire("startDrag", arguments);
+                };
+
+                this.dd.onDrag = function () {
+                    me.syncPosition();
+                    me.cfg.refireEvent("iframe");
+                    if (this.platform == "mac" && YAHOO.env.ua.gecko) {
+                        this.showMacGeckoScrollbars();
+                    }
+
+                    me.dragEvent.fire("onDrag", arguments);
+                };
+
+                this.dd.endDrag = function () {
+
+                    if (YAHOO.env.ua.ie == 6) {
+                        Dom.removeClass(me.element,"drag");
+                    }
+
+                    me.dragEvent.fire("endDrag", arguments);
+                    me.moveEvent.fire(me.cfg.getProperty("xy"));
+
+                };
+
+                this.dd.setHandleElId(this.header.id);
+                this.dd.addInvalidHandleType("INPUT");
+                this.dd.addInvalidHandleType("SELECT");
+                this.dd.addInvalidHandleType("TEXTAREA");
+            }
+        },
+        
+        /**
+        * Builds the mask that is laid over the document when the Panel is 
+        * configured to be modal.
+        * @method buildMask
+        */
+        buildMask: function () {
+            var oMask = this.mask;
+            if (!oMask) {
+                if (!m_oMaskTemplate) {
+                    m_oMaskTemplate = document.createElement("div");
+                    m_oMaskTemplate.className = "mask";
+                    m_oMaskTemplate.innerHTML = "&#160;";
+                }
+                oMask = m_oMaskTemplate.cloneNode(true);
+                oMask.id = this.id + "_mask";
+
+                document.body.insertBefore(oMask, document.body.firstChild);
+
+                this.mask = oMask;
+
+                if (YAHOO.env.ua.gecko && this.platform == "mac") {
+                    Dom.addClass(this.mask, "block-scrollbars");
+                }
+
+                // Stack mask based on the element zindex
+                this.stackMask();
+            }
+        },
+
+        /**
+        * Hides the modality mask.
+        * @method hideMask
+        */
+        hideMask: function () {
+            if (this.cfg.getProperty("modal") && this.mask) {
+                this.mask.style.display = "none";
+                Dom.removeClass(document.body, "masked");
+                this.hideMaskEvent.fire();
+            }
+        },
+
+        /**
+        * Shows the modality mask.
+        * @method showMask
+        */
+        showMask: function () {
+            if (this.cfg.getProperty("modal") && this.mask) {
+                Dom.addClass(document.body, "masked");
+                this.sizeMask();
+                this.mask.style.display = "block";
+                this.showMaskEvent.fire();
+            }
+        },
+
+        /**
+        * Sets the size of the modality mask to cover the entire scrollable 
+        * area of the document
+        * @method sizeMask
+        */
+        sizeMask: function () {
+            if (this.mask) {
+
+                // Shrink mask first, so it doesn't affect the document size.
+                var mask = this.mask,
+                    viewWidth = Dom.getViewportWidth(),
+                    viewHeight = Dom.getViewportHeight();
+
+                if (mask.offsetHeight > viewHeight) {
+                    mask.style.height = viewHeight + "px";
+                }
+
+                if (mask.offsetWidth > viewWidth) {
+                    mask.style.width = viewWidth + "px";
+                }
+
+                // Then size it to the document
+                mask.style.height = Dom.getDocumentHeight() + "px";
+                mask.style.width = Dom.getDocumentWidth() + "px";
+            }
+        },
+
+        /**
+         * Sets the zindex of the mask, if it exists, based on the zindex of 
+         * the Panel element. The zindex of the mask is set to be one less 
+         * than the Panel element's zindex.
+         * 
+         * <p>NOTE: This method will not bump up the zindex of the Panel
+         * to ensure that the mask has a non-negative zindex. If you require the
+         * mask zindex to be 0 or higher, the zindex of the Panel 
+         * should be set to a value higher than 0, before this method is called.
+         * </p>
+         * @method stackMask
+         */
+        stackMask: function() {
+            if (this.mask) {
+                var panelZ = Dom.getStyle(this.element, "zIndex");
+                if (!YAHOO.lang.isUndefined(panelZ) && !isNaN(panelZ)) {
+                    Dom.setStyle(this.mask, "zIndex", panelZ - 1);
+                }
+            }
+        },
+
+        /**
+        * Renders the Panel by inserting the elements that are not already in 
+        * the main Panel into their correct places. Optionally appends the 
+        * Panel to the specified node prior to the render's execution. NOTE: 
+        * For Panels without existing markup, the appendToNode argument is 
+        * REQUIRED. If this argument is ommitted and the current element is 
+        * not present in the document, the function will return false, 
+        * indicating that the render was a failure.
+        * @method render
+        * @param {String} appendToNode The element id to which the Module 
+        * should be appended to prior to rendering <em>OR</em>
+        * @param {HTMLElement} appendToNode The element to which the Module 
+        * should be appended to prior to rendering
+        * @return {boolean} Success or failure of the render
+        */
+        render: function (appendToNode) {
+
+            return Panel.superclass.render.call(this, 
+                appendToNode, this.innerElement);
+
+        },
+        
+        /**
+        * Removes the Panel element from the DOM and sets all child elements
+        * to null.
+        * @method destroy
+        */
+        destroy: function () {
+            Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
+            this.removeMask();
+            if (this.close) {
+                Event.purgeElement(this.close);
+            }
+            Panel.superclass.destroy.call(this);  
+        },
+
+        /**
+         * Forces the underlay element to be repainted through the application/removal 
+         * of a yui-force-redraw class to the underlay element.
+         *
+         * @method forceUnderlayRedraw
+         */
+        forceUnderlayRedraw : function () {
+            var u = this.underlay;
+            Dom.addClass(u, "yui-force-redraw");
+            setTimeout(function(){Dom.removeClass(u, "yui-force-redraw");}, 0);
+        },
+
+        /**
+        * Returns a String representation of the object.
+        * @method toString
+        * @return {String} The string representation of the Panel.
+        */
+        toString: function () {
+            return "Panel " + this.id;
+        }
+    
+    });
+
+}());
+
+(function () {
+
+    /**
+    * <p>
+    * Dialog is an implementation of Panel that can be used to submit form 
+    * data.
+    * </p>
+    * <p>
+    * Built-in functionality for buttons with event handlers is included. 
+    * If the optional YUI Button dependancy is included on the page, the buttons
+    * created will be instances of YAHOO.widget.Button, otherwise regular HTML buttons
+    * will be created.
+    * </p>
+    * <p>
+    * Forms can be processed in 3 ways -- via an asynchronous Connection utility call, 
+    * a simple form POST or GET, or manually. The YUI Connection utility should be
+    * included if you're using the default "async" postmethod, but is not required if
+    * you're using any of the other postmethod values.
+    * </p>
+    * @namespace YAHOO.widget
+    * @class Dialog
+    * @extends YAHOO.widget.Panel
+    * @constructor
+    * @param {String} el The element ID representing the Dialog <em>OR</em>
+    * @param {HTMLElement} el The element representing the Dialog
+    * @param {Object} userConfig The configuration object literal containing 
+    * the configuration that should be set for this Dialog. See configuration 
+    * documentation for more details.
+    */
+    YAHOO.widget.Dialog = function (el, userConfig) {
+        YAHOO.widget.Dialog.superclass.constructor.call(this, el, userConfig);
+    };
+
+    var Event = YAHOO.util.Event,
+        CustomEvent = YAHOO.util.CustomEvent,
+        Dom = YAHOO.util.Dom,
+        Dialog = YAHOO.widget.Dialog,
+        Lang = YAHOO.lang,
+
+        /**
+         * Constant representing the name of the Dialog's events
+         * @property EVENT_TYPES
+         * @private
+         * @final
+         * @type Object
+         */
+        EVENT_TYPES = {
+            "BEFORE_SUBMIT": "beforeSubmit",
+            "SUBMIT": "submit",
+            "MANUAL_SUBMIT": "manualSubmit",
+            "ASYNC_SUBMIT": "asyncSubmit",
+            "FORM_SUBMIT": "formSubmit",
+            "CANCEL": "cancel"
+        },
+
+        /**
+        * Constant representing the Dialog's configuration properties
+        * @property DEFAULT_CONFIG
+        * @private
+        * @final
+        * @type Object
+        */
+        DEFAULT_CONFIG = {
+
+            "POST_METHOD": { 
+                key: "postmethod", 
+                value: "async"
+            },
+
+            "POST_DATA" : {
+                key: "postdata",
+                value: null
+            },
+
+            "BUTTONS": {
+                key: "buttons",
+                value: "none",
+                supercedes: ["visible"]
+            },
+
+            "HIDEAFTERSUBMIT" : {
+                key: "hideaftersubmit",
+                value: true
+            }
+
+        };
+
+    /**
+    * Constant representing the default CSS class used for a Dialog
+    * @property YAHOO.widget.Dialog.CSS_DIALOG
+    * @static
+    * @final
+    * @type String
+    */
+    Dialog.CSS_DIALOG = "yui-dialog";
+
+    function removeButtonEventHandlers() {
+
+        var aButtons = this._aButtons,
+            nButtons,
+            oButton,
+            i;
+
+        if (Lang.isArray(aButtons)) {
+            nButtons = aButtons.length;
+
+            if (nButtons > 0) {
+                i = nButtons - 1;
+                do {
+                    oButton = aButtons[i];
+
+                    if (YAHOO.widget.Button && oButton instanceof YAHOO.widget.Button) {
+                        oButton.destroy();
+                    }
+                    else if (oButton.tagName.toUpperCase() == "BUTTON") {
+                        Event.purgeElement(oButton);
+                        Event.purgeElement(oButton, false);
+                    }
+                }
+                while (i--);
+            }
+        }
+    }
+
+    YAHOO.extend(Dialog, YAHOO.widget.Panel, { 
+
+        /**
+        * @property form
+        * @description Object reference to the Dialog's 
+        * <code>&#60;form&#62;</code> element.
+        * @default null 
+        * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
+        * level-one-html.html#ID-40002357">HTMLFormElement</a>
+        */
+        form: null,
+    
+        /**
+        * Initializes the class's configurable properties which can be changed 
+        * using the Dialog's Config object (cfg).
+        * @method initDefaultConfig
+        */
+        initDefaultConfig: function () {
+            Dialog.superclass.initDefaultConfig.call(this);
+
+            /**
+            * The internally maintained callback object for use with the 
+            * Connection utility. The format of the callback object is 
+            * similar to Connection Manager's callback object and is 
+            * simply passed through to Connection Manager when the async 
+            * request is made.
+            * @property callback
+            * @type Object
+            */
+            this.callback = {
+
+                /**
+                * The function to execute upon success of the 
+                * Connection submission (when the form does not
+                * contain a file input element).
+                * 
+                * @property callback.success
+                * @type Function
+                */
+                success: null,
+
+                /**
+                * The function to execute upon failure of the 
+                * Connection submission
+                * @property callback.failure
+                * @type Function
+                */
+                failure: null,
+
+                /**
+                *<p>
+                * The function to execute upon success of the 
+                * Connection submission, when the form contains
+                * a file input element.
+                * </p>
+                * <p>
+                * <em>NOTE:</em> Connection manager will not
+                * invoke the success or failure handlers for the file
+                * upload use case. This will be the only callback
+                * handler invoked.
+                * </p>
+                * <p>
+                * For more information, see the <a href="http://developer.yahoo.com/yui/connection/#file">
+                * Connection Manager documenation on file uploads</a>.
+                * </p>
+                * @property callback.upload
+                * @type Function
+                */
+
+                /**
+                * The arbitraty argument or arguments to pass to the Connection 
+                * callback functions
+                * @property callback.argument
+                * @type Object
+                */
+                argument: null
+
+            };
+
+            // Add form dialog config properties //
+            /**
+            * The method to use for posting the Dialog's form. Possible values 
+            * are "async", "form", and "manual".
+            * @config postmethod
+            * @type String
+            * @default async
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.POST_METHOD.key, {
+                handler: this.configPostMethod, 
+                value: DEFAULT_CONFIG.POST_METHOD.value, 
+                validator: function (val) {
+                    if (val != "form" && val != "async" && val != "none" && 
+                        val != "manual") {
+                        return false;
+                    } else {
+                        return true;
+                    }
+                }
+            });
+
+            /**
+            * Any additional post data which needs to be sent when using the 
+            * <a href="#config_postmethod">async</a> postmethod for dialog POST submissions.
+            * The format for the post data string is defined by Connection Manager's 
+            * <a href="YAHOO.util.Connect.html#method_asyncRequest">asyncRequest</a> 
+            * method.
+            * @config postdata
+            * @type String
+            * @default null
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.POST_DATA.key, {
+                value: DEFAULT_CONFIG.POST_DATA.value
+            });
+
+            /**
+            * This property is used to configure whether or not the 
+            * dialog should be automatically hidden after submit.
+            * 
+            * @config hideaftersubmit
+            * @type Boolean
+            * @default true
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.HIDEAFTERSUBMIT.key, {
+                value: DEFAULT_CONFIG.HIDEAFTERSUBMIT.value
+            });
+
+            /**
+            * Array of object literals, each containing a set of properties 
+            * defining a button to be appended into the Dialog's footer.
+            *
+            * <p>Each button object in the buttons array can have three properties:</p>
+            * <dl>
+            *    <dt>text:</dt>
+            *    <dd>
+            *       The text that will display on the face of the button. The text can 
+            *       include HTML, as long as it is compliant with HTML Button specifications.
+            *    </dd>
+            *    <dt>handler:</dt>
+            *    <dd>Can be either:
+            *    <ol>
+            *       <li>A reference to a function that should fire when the 
+            *       button is clicked.  (In this case scope of this function is 
+            *       always its Dialog instance.)</li>
+            *
+            *       <li>An object literal representing the code to be 
+            *       executed when the button is clicked.
+            *       
+            *       <p>Format:</p>
+            *
+            *       <p>
+            *       <code>{
+            *       <br>
+            *       <strong>fn:</strong> Function, &#47;&#47;
+            *       The handler to call when  the event fires.
+            *       <br>
+            *       <strong>obj:</strong> Object, &#47;&#47; 
+            *       An  object to pass back to the handler.
+            *       <br>
+            *       <strong>scope:</strong> Object &#47;&#47; 
+            *       The object to use for the scope of the handler.
+            *       <br>
+            *       }</code>
+            *       </p>
+            *       </li>
+            *     </ol>
+            *     </dd>
+            *     <dt>isDefault:</dt>
+            *     <dd>
+            *        An optional boolean value that specifies that a button 
+            *        should be highlighted and focused by default.
+            *     </dd>
+            * </dl>
+            *
+            * <em>NOTE:</em>If the YUI Button Widget is included on the page, 
+            * the buttons created will be instances of YAHOO.widget.Button. 
+            * Otherwise, HTML Buttons (<code>&#60;BUTTON&#62;</code>) will be 
+            * created.
+            *
+            * @config buttons
+            * @type {Array|String}
+            * @default "none"
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.BUTTONS.key, {
+                handler: this.configButtons,
+                value: DEFAULT_CONFIG.BUTTONS.value,
+                supercedes : DEFAULT_CONFIG.BUTTONS.supercedes
+            }); 
+
+        },
+
+        /**
+        * Initializes the custom events for Dialog which are fired 
+        * automatically at appropriate times by the Dialog class.
+        * @method initEvents
+        */
+        initEvents: function () {
+            Dialog.superclass.initEvents.call(this);
+
+            var SIGNATURE = CustomEvent.LIST;
+
+            /**
+            * CustomEvent fired prior to submission
+            * @event beforeSubmitEvent
+            */ 
+            this.beforeSubmitEvent = 
+                this.createEvent(EVENT_TYPES.BEFORE_SUBMIT);
+            this.beforeSubmitEvent.signature = SIGNATURE;
+            
+            /**
+            * CustomEvent fired after submission
+            * @event submitEvent
+            */
+            this.submitEvent = this.createEvent(EVENT_TYPES.SUBMIT);
+            this.submitEvent.signature = SIGNATURE;
+        
+            /**
+            * CustomEvent fired for manual submission, before the generic submit event is fired
+            * @event manualSubmitEvent
+            */
+            this.manualSubmitEvent = 
+                this.createEvent(EVENT_TYPES.MANUAL_SUBMIT);
+            this.manualSubmitEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired after asynchronous submission, before the generic submit event is fired
+            *
+            * @event asyncSubmitEvent
+            * @param {Object} conn The connection object, returned by YAHOO.util.Connect.asyncRequest
+            */
+            this.asyncSubmitEvent = this.createEvent(EVENT_TYPES.ASYNC_SUBMIT);
+            this.asyncSubmitEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired after form-based submission, before the generic submit event is fired
+            * @event formSubmitEvent
+            */
+            this.formSubmitEvent = this.createEvent(EVENT_TYPES.FORM_SUBMIT);
+            this.formSubmitEvent.signature = SIGNATURE;
+
+            /**
+            * CustomEvent fired after cancel
+            * @event cancelEvent
+            */
+            this.cancelEvent = this.createEvent(EVENT_TYPES.CANCEL);
+            this.cancelEvent.signature = SIGNATURE;
+        
+        },
+        
+        /**
+        * The Dialog initialization method, which is executed for Dialog and 
+        * all of its subclasses. This method is automatically called by the 
+        * constructor, and  sets up all DOM references for pre-existing markup, 
+        * and creates required markup if it is not already present.
+        * 
+        * @method init
+        * @param {String} el The element ID representing the Dialog <em>OR</em>
+        * @param {HTMLElement} el The element representing the Dialog
+        * @param {Object} userConfig The configuration object literal 
+        * containing the configuration that should be set for this Dialog. 
+        * See configuration documentation for more details.
+        */
+        init: function (el, userConfig) {
+
+            /*
+                 Note that we don't pass the user config in here yet because 
+                 we only want it executed once, at the lowest subclass level
+            */
+
+            Dialog.superclass.init.call(this, el/*, userConfig*/); 
+
+            this.beforeInitEvent.fire(Dialog);
+
+            Dom.addClass(this.element, Dialog.CSS_DIALOG);
+
+            this.cfg.setProperty("visible", false);
+
+            if (userConfig) {
+                this.cfg.applyConfig(userConfig, true);
+            }
+
+            this.showEvent.subscribe(this.focusFirst, this, true);
+            this.beforeHideEvent.subscribe(this.blurButtons, this, true);
+
+            this.subscribe("changeBody", this.registerForm);
+
+            this.initEvent.fire(Dialog);
+        },
+
+        /**
+        * Submits the Dialog's form depending on the value of the 
+        * "postmethod" configuration property.  <strong>Please note:
+        * </strong> As of version 2.3 this method will automatically handle 
+        * asyncronous file uploads should the Dialog instance's form contain 
+        * <code>&#60;input type="file"&#62;</code> elements.  If a Dialog 
+        * instance will be handling asyncronous file uploads, its 
+        * <code>callback</code> property will need to be setup with a 
+        * <code>upload</code> handler rather than the standard 
+        * <code>success</code> and, or <code>failure</code> handlers.  For more 
+        * information, see the <a href="http://developer.yahoo.com/yui/
+        * connection/#file">Connection Manager documenation on file uploads</a>.
+        * @method doSubmit
+        */
+        doSubmit: function () {
+
+            var Connect = YAHOO.util.Connect,
+                oForm = this.form,
+                bUseFileUpload = false,
+                bUseSecureFileUpload = false,
+                aElements,
+                nElements,
+                i,
+                formAttrs;
+
+            switch (this.cfg.getProperty("postmethod")) {
+
+                case "async":
+                    aElements = oForm.elements;
+                    nElements = aElements.length;
+
+                    if (nElements > 0) {
+                        i = nElements - 1;
+                        do {
+                            if (aElements[i].type == "file") {
+                                bUseFileUpload = true;
+                                break;
+                            }
+                        }
+                        while(i--);
+                    }
+
+                    if (bUseFileUpload && YAHOO.env.ua.ie && this.isSecure) {
+                        bUseSecureFileUpload = true;
+                    }
+
+                    formAttrs = this._getFormAttributes(oForm);
+
+                    Connect.setForm(oForm, bUseFileUpload, bUseSecureFileUpload);
+
+                    var postData = this.cfg.getProperty("postdata");
+                    var c = Connect.asyncRequest(formAttrs.method, formAttrs.action, this.callback, postData);
+
+                    this.asyncSubmitEvent.fire(c);
+
+                    break;
+
+                case "form":
+                    oForm.submit();
+                    this.formSubmitEvent.fire();
+                    break;
+
+                case "none":
+                case "manual":
+                    this.manualSubmitEvent.fire();
+                    break;
+            }
+        },
+
+        /**
+         * Retrieves important attributes (currently method and action) from
+         * the form element, accounting for any elements which may have the same name 
+         * as the attributes. Defaults to "POST" and "" for method and action respectively
+         * if the attribute cannot be retrieved.
+         *
+         * @method _getFormAttributes
+         * @protected
+         * @param {HTMLFormElement} oForm The HTML Form element from which to retrieve the attributes
+         * @return {Object} Object literal, with method and action String properties.
+         */
+        _getFormAttributes : function(oForm){
+            var attrs = {
+                method : null,
+                action : null
+            };
+
+            if (oForm) {
+                if (oForm.getAttributeNode) {
+                    var action = oForm.getAttributeNode("action");
+                    var method = oForm.getAttributeNode("method");
+
+                    if (action) {
+                        attrs.action = action.value;
+                    }
+
+                    if (method) {
+                        attrs.method = method.value;
+                    }
+
+                } else {
+                    attrs.action = oForm.getAttribute("action");
+                    attrs.method = oForm.getAttribute("method");
+                }
+            }
+
+            attrs.method = (Lang.isString(attrs.method) ? attrs.method : "POST").toUpperCase();
+            attrs.action = Lang.isString(attrs.action) ? attrs.action : "";
+
+            return attrs;
+        },
+
+        /**
+        * Prepares the Dialog's internal FORM object, creating one if one is
+        * not currently present.
+        * @method registerForm
+        */
+        registerForm: function() {
+
+            var form = this.element.getElementsByTagName("form")[0];
+
+            if (this.form) {
+                if (this.form == form && Dom.isAncestor(this.element, this.form)) {
+                    return;
+                } else {
+                    Event.purgeElement(this.form);
+                    this.form = null;
+                }
+            }
+
+            if (!form) {
+                form = document.createElement("form");
+                form.name = "frm_" + this.id;
+                this.body.appendChild(form);
+            }
+
+            if (form) {
+                this.form = form;
+                Event.on(form, "submit", this._submitHandler, this, true);
+            }
+        },
+
+        /**
+         * Internal handler for the form submit event
+         *
+         * @method _submitHandler
+         * @protected
+         * @param {DOMEvent} e The DOM Event object
+         */
+        _submitHandler : function(e) {
+            Event.stopEvent(e);
+            this.submit();
+            this.form.blur();
+        },
+
+        /**
+         * Sets up a tab, shift-tab loop between the first and last elements
+         * provided. NOTE: Sets up the preventBackTab and preventTabOut KeyListener
+         * instance properties, which are reset everytime this method is invoked.
+         *
+         * @method setTabLoop
+         * @param {HTMLElement} firstElement
+         * @param {HTMLElement} lastElement
+         *
+         */
+        setTabLoop : function(firstElement, lastElement) {
+
+            firstElement = firstElement || this.firstButton;
+            lastElement = this.lastButton || lastElement;
+
+            Dialog.superclass.setTabLoop.call(this, firstElement, lastElement);
+        },
+
+        /**
+         * Configures instance properties, pointing to the 
+         * first and last focusable elements in the Dialog's form.
+         *
+         * @method setFirstLastFocusable
+         */
+        setFirstLastFocusable : function() {
+
+            Dialog.superclass.setFirstLastFocusable.call(this);
+
+            var i, l, el, elements = this.focusableElements;
+
+            this.firstFormElement = null;
+            this.lastFormElement = null;
+
+            if (this.form && elements && elements.length > 0) {
+                l = elements.length;
+
+                for (i = 0; i < l; ++i) {
+                    el = elements[i];
+                    if (this.form === el.form) {
+                        this.firstFormElement = el;
+                        break;
+                    }
+                }
+
+                for (i = l-1; i >= 0; --i) {
+                    el = elements[i];
+                    if (this.form === el.form) {
+                        this.lastFormElement = el;
+                        break;
+                    }
+                }
+            }
+        },
+
+        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
+        /**
+        * The default event handler fired when the "close" property is 
+        * changed. The method controls the appending or hiding of the close
+        * icon at the top right of the Dialog.
+        * @method configClose
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For 
+        * configuration handlers, args[0] will equal the newly applied value 
+        * for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configClose: function (type, args, obj) {
+            Dialog.superclass.configClose.apply(this, arguments);
+        },
+
+        /**
+         * Event handler for the close icon
+         * 
+         * @method _doClose
+         * @protected
+         * 
+         * @param {DOMEvent} e
+         */
+         _doClose : function(e) {
+            Event.preventDefault(e);
+            this.cancel();
+        },
+
+        /**
+        * The default event handler for the "buttons" configuration property
+        * @method configButtons
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configButtons: function (type, args, obj) {
+
+            var Button = YAHOO.widget.Button,
+                aButtons = args[0],
+                oInnerElement = this.innerElement,
+                oButton,
+                oButtonEl,
+                oYUIButton,
+                nButtons,
+                oSpan,
+                oFooter,
+                i;
+
+            removeButtonEventHandlers.call(this);
+
+            this._aButtons = null;
+
+            if (Lang.isArray(aButtons)) {
+
+                oSpan = document.createElement("span");
+                oSpan.className = "button-group";
+                nButtons = aButtons.length;
+
+                this._aButtons = [];
+                this.defaultHtmlButton = null;
+
+                for (i = 0; i < nButtons; i++) {
+                    oButton = aButtons[i];
+
+                    if (Button) {
+                        oYUIButton = new Button({ label: oButton.text});
+                        oYUIButton.appendTo(oSpan);
+
+                        oButtonEl = oYUIButton.get("element");
+
+                        if (oButton.isDefault) {
+                            oYUIButton.addClass("default");
+                            this.defaultHtmlButton = oButtonEl;
+                        }
+
+                        if (Lang.isFunction(oButton.handler)) {
+
+                            oYUIButton.set("onclick", { 
+                                fn: oButton.handler, 
+                                obj: this, 
+                                scope: this 
+                            });
+
+                        } else if (Lang.isObject(oButton.handler) && Lang.isFunction(oButton.handler.fn)) {
+
+                            oYUIButton.set("onclick", { 
+                                fn: oButton.handler.fn, 
+                                obj: ((!Lang.isUndefined(oButton.handler.obj)) ? oButton.handler.obj : this), 
+                                scope: (oButton.handler.scope || this) 
+                            });
+
+                        }
+
+                        this._aButtons[this._aButtons.length] = oYUIButton;
+
+                    } else {
+
+                        oButtonEl = document.createElement("button");
+                        oButtonEl.setAttribute("type", "button");
+
+                        if (oButton.isDefault) {
+                            oButtonEl.className = "default";
+                            this.defaultHtmlButton = oButtonEl;
+                        }
+
+                        oButtonEl.innerHTML = oButton.text;
+
+                        if (Lang.isFunction(oButton.handler)) {
+                            Event.on(oButtonEl, "click", oButton.handler, this, true);
+                        } else if (Lang.isObject(oButton.handler) && 
+                            Lang.isFunction(oButton.handler.fn)) {
+    
+                            Event.on(oButtonEl, "click", 
+                                oButton.handler.fn, 
+                                ((!Lang.isUndefined(oButton.handler.obj)) ? oButton.handler.obj : this), 
+                                (oButton.handler.scope || this));
+                        }
+
+                        oSpan.appendChild(oButtonEl);
+                        this._aButtons[this._aButtons.length] = oButtonEl;
+                    }
+
+                    oButton.htmlButton = oButtonEl;
+
+                    if (i === 0) {
+                        this.firstButton = oButtonEl;
+                    }
+
+                    if (i == (nButtons - 1)) {
+                        this.lastButton = oButtonEl;
+                    }
+                }
+
+                this.setFooter(oSpan);
+
+                oFooter = this.footer;
+
+                if (Dom.inDocument(this.element) && !Dom.isAncestor(oInnerElement, oFooter)) {
+                    oInnerElement.appendChild(oFooter);
+                }
+
+                this.buttonSpan = oSpan;
+
+            } else { // Do cleanup
+                oSpan = this.buttonSpan;
+                oFooter = this.footer;
+                if (oSpan && oFooter) {
+                    oFooter.removeChild(oSpan);
+                    this.buttonSpan = null;
+                    this.firstButton = null;
+                    this.lastButton = null;
+                    this.defaultHtmlButton = null;
+                }
+            }
+
+            this.changeContentEvent.fire();
+        },
+
+        /**
+        * @method getButtons
+        * @description Returns an array containing each of the Dialog's 
+        * buttons, by default an array of HTML <code>&#60;BUTTON&#62;</code> 
+        * elements.  If the Dialog's buttons were created using the 
+        * YAHOO.widget.Button class (via the inclusion of the optional Button 
+        * dependancy on the page), an array of YAHOO.widget.Button instances 
+        * is returned.
+        * @return {Array}
+        */
+        getButtons: function () {
+            return this._aButtons || null;
+        },
+
+        /**
+         * <p>
+         * Sets focus to the first focusable element in the Dialog's form if found, 
+         * else, the default button if found, else the first button defined via the 
+         * "buttons" configuration property.
+         * </p>
+         * <p>
+         * This method is invoked when the Dialog is made visible.
+         * </p>
+         * @method focusFirst
+         */
+        focusFirst: function (type, args, obj) {
+
+            var el = this.firstFormElement;
+
+            if (args && args[1]) {
+                Event.stopEvent(args[1]);
+            }
+
+            if (el) {
+                try {
+                    el.focus();
+                } catch(oException) {
+                    // Ignore
+                }
+            } else {
+                if (this.defaultHtmlButton) {
+                    this.focusDefaultButton();
+                } else {
+                    this.focusFirstButton();
+                }
+            }
+        },
+
+        /**
+        * Sets focus to the last element in the Dialog's form or the last 
+        * button defined via the "buttons" configuration property.
+        * @method focusLast
+        */
+        focusLast: function (type, args, obj) {
+
+            var aButtons = this.cfg.getProperty("buttons"),
+                el = this.lastFormElement;
+
+            if (args && args[1]) {
+                Event.stopEvent(args[1]);
+            }
+
+            if (aButtons && Lang.isArray(aButtons)) {
+                this.focusLastButton();
+            } else {
+                if (el) {
+                    try {
+                        el.focus();
+                    } catch(oException) {
+                        // Ignore
+                    }
+                }
+            }
+        },
+
+        /**
+         * Helper method to normalize button references. It either returns the 
+         * YUI Button instance for the given element if found,
+         * or the passes back the HTMLElement reference if a corresponding YUI Button
+         * reference is not found or YAHOO.widget.Button does not exist on the page.
+         *
+         * @method _getButton
+         * @private
+         * @param {HTMLElement} button
+         * @return {YAHOO.widget.Button|HTMLElement}
+         */
+        _getButton : function(button) {
+            var Button = YAHOO.widget.Button;
+
+            // If we have an HTML button and YUI Button is on the page, 
+            // get the YUI Button reference if available.
+            if (Button && button && button.nodeName && button.id) {
+                button = Button.getButton(button.id) || button;
+            }
+
+            return button;
+        },
+
+        /**
+        * Sets the focus to the button that is designated as the default via 
+        * the "buttons" configuration property. By default, this method is 
+        * called when the Dialog is made visible.
+        * @method focusDefaultButton
+        */
+        focusDefaultButton: function () {
+            var button = this._getButton(this.defaultHtmlButton);
+            if (button) {
+                /*
+                    Place the call to the "focus" method inside a try/catch
+                    block to prevent IE from throwing JavaScript errors if
+                    the element is disabled or hidden.
+                */
+                try {
+                    button.focus();
+                } catch(oException) {
+                }
+            }
+        },
+
+        /**
+        * Blurs all the buttons defined via the "buttons" 
+        * configuration property.
+        * @method blurButtons
+        */
+        blurButtons: function () {
+            
+            var aButtons = this.cfg.getProperty("buttons"),
+                nButtons,
+                oButton,
+                oElement,
+                i;
+
+            if (aButtons && Lang.isArray(aButtons)) {
+                nButtons = aButtons.length;
+                if (nButtons > 0) {
+                    i = (nButtons - 1);
+                    do {
+                        oButton = aButtons[i];
+                        if (oButton) {
+                            oElement = this._getButton(oButton.htmlButton);
+                            if (oElement) {
+                                /*
+                                    Place the call to the "blur" method inside  
+                                    a try/catch block to prevent IE from  
+                                    throwing JavaScript errors if the element 
+                                    is disabled or hidden.
+                                */
+                                try {
+                                    oElement.blur();
+                                } catch(oException) {
+                                    // ignore
+                                }
+                            }
+                        }
+                    } while(i--);
+                }
+            }
+        },
+
+        /**
+        * Sets the focus to the first button created via the "buttons"
+        * configuration property.
+        * @method focusFirstButton
+        */
+        focusFirstButton: function () {
+
+            var aButtons = this.cfg.getProperty("buttons"),
+                oButton,
+                oElement;
+
+            if (aButtons && Lang.isArray(aButtons)) {
+                oButton = aButtons[0];
+                if (oButton) {
+                    oElement = this._getButton(oButton.htmlButton);
+                    if (oElement) {
+                        /*
+                            Place the call to the "focus" method inside a 
+                            try/catch block to prevent IE from throwing 
+                            JavaScript errors if the element is disabled 
+                            or hidden.
+                        */
+                        try {
+                            oElement.focus();
+                        } catch(oException) {
+                            // ignore
+                        }
+                    }
+                }
+            }
+        },
+
+        /**
+        * Sets the focus to the last button created via the "buttons" 
+        * configuration property.
+        * @method focusLastButton
+        */
+        focusLastButton: function () {
+
+            var aButtons = this.cfg.getProperty("buttons"),
+                nButtons,
+                oButton,
+                oElement;
+
+            if (aButtons && Lang.isArray(aButtons)) {
+                nButtons = aButtons.length;
+                if (nButtons > 0) {
+                    oButton = aButtons[(nButtons - 1)];
+
+                    if (oButton) {
+                        oElement = this._getButton(oButton.htmlButton);
+                        if (oElement) {
+                            /*
+                                Place the call to the "focus" method inside a 
+                                try/catch block to prevent IE from throwing 
+                                JavaScript errors if the element is disabled
+                                or hidden.
+                            */
+        
+                            try {
+                                oElement.focus();
+                            } catch(oException) {
+                                // Ignore
+                            }
+                        }
+                    }
+                }
+            }
+        },
+
+        /**
+        * The default event handler for the "postmethod" configuration property
+        * @method configPostMethod
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For 
+        * configuration handlers, args[0] will equal the newly applied value 
+        * for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configPostMethod: function (type, args, obj) {
+            this.registerForm();
+        },
+
+        // END BUILT-IN PROPERTY EVENT HANDLERS //
+        
+        /**
+        * Built-in function hook for writing a validation function that will 
+        * be checked for a "true" value prior to a submit. This function, as 
+        * implemented by default, always returns true, so it should be 
+        * overridden if validation is necessary.
+        * @method validate
+        */
+        validate: function () {
+            return true;
+        },
+        
+        /**
+        * Executes a submit of the Dialog if validation 
+        * is successful. By default the Dialog is hidden
+        * after submission, but you can set the "hideaftersubmit"
+        * configuration property to false, to prevent the Dialog
+        * from being hidden.
+        * 
+        * @method submit
+        */
+        submit: function () {
+            if (this.validate()) {
+                this.beforeSubmitEvent.fire();
+                this.doSubmit();
+                this.submitEvent.fire();
+
+                if (this.cfg.getProperty("hideaftersubmit")) {
+                    this.hide();
+                }
+
+                return true;
+            } else {
+                return false;
+            }
+        },
+
+        /**
+        * Executes the cancel of the Dialog followed by a hide.
+        * @method cancel
+        */
+        cancel: function () {
+            this.cancelEvent.fire();
+            this.hide();
+        },
+        
+        /**
+        * Returns a JSON-compatible data structure representing the data 
+        * currently contained in the form.
+        * @method getData
+        * @return {Object} A JSON object reprsenting the data of the 
+        * current form.
+        */
+        getData: function () {
+
+            var oForm = this.form,
+                aElements,
+                nTotalElements,
+                oData,
+                sName,
+                oElement,
+                nElements,
+                sType,
+                sTagName,
+                aOptions,
+                nOptions,
+                aValues,
+                oOption,
+                sValue,
+                oRadio,
+                oCheckbox,
+                i,
+                n;    
+    
+            function isFormElement(p_oElement) {
+                var sTag = p_oElement.tagName.toUpperCase();
+                return ((sTag == "INPUT" || sTag == "TEXTAREA" || 
+                        sTag == "SELECT") && p_oElement.name == sName);
+            }
+
+            if (oForm) {
+
+                aElements = oForm.elements;
+                nTotalElements = aElements.length;
+                oData = {};
+
+                for (i = 0; i < nTotalElements; i++) {
+                    sName = aElements[i].name;
+
+                    /*
+                        Using "Dom.getElementsBy" to safeguard user from JS 
+                        errors that result from giving a form field (or set of 
+                        fields) the same name as a native method of a form 
+                        (like "submit") or a DOM collection (such as the "item"
+                        method). Originally tried accessing fields via the 
+                        "namedItem" method of the "element" collection, but 
+                        discovered that it won't return a collection of fields 
+                        in Gecko.
+                    */
+
+                    oElement = Dom.getElementsBy(isFormElement, "*", oForm);
+                    nElements = oElement.length;
+
+                    if (nElements > 0) {
+                        if (nElements == 1) {
+                            oElement = oElement[0];
+
+                            sType = oElement.type;
+                            sTagName = oElement.tagName.toUpperCase();
+
+                            switch (sTagName) {
+                                case "INPUT":
+                                    if (sType == "checkbox") {
+                                        oData[sName] = oElement.checked;
+                                    } else if (sType != "radio") {
+                                        oData[sName] = oElement.value;
+                                    }
+                                    break;
+
+                                case "TEXTAREA":
+                                    oData[sName] = oElement.value;
+                                    break;
+    
+                                case "SELECT":
+                                    aOptions = oElement.options;
+                                    nOptions = aOptions.length;
+                                    aValues = [];
+    
+                                    for (n = 0; n < nOptions; n++) {
+                                        oOption = aOptions[n];
+    
+                                        if (oOption.selected) {
+                                            sValue = oOption.value;
+                                            if (!sValue || sValue === "") {
+                                                sValue = oOption.text;
+                                            }
+                                            aValues[aValues.length] = sValue;
+                                        }
+                                    }
+                                    oData[sName] = aValues;
+                                    break;
+                            }
+        
+                        } else {
+                            sType = oElement[0].type;
+                            switch (sType) {
+                                case "radio":
+                                    for (n = 0; n < nElements; n++) {
+                                        oRadio = oElement[n];
+                                        if (oRadio.checked) {
+                                            oData[sName] = oRadio.value;
+                                            break;
+                                        }
+                                    }
+                                    break;
+        
+                                case "checkbox":
+                                    aValues = [];
+                                    for (n = 0; n < nElements; n++) {
+                                        oCheckbox = oElement[n];
+                                        if (oCheckbox.checked) {
+                                            aValues[aValues.length] =  oCheckbox.value;
+                                        }
+                                    }
+                                    oData[sName] = aValues;
+                                    break;
+                            }
+                        }
+                    }
+                }
+            }
+
+            return oData;
+        },
+
+        /**
+        * Removes the Panel element from the DOM and sets all child elements 
+        * to null.
+        * @method destroy
+        */
+        destroy: function () {
+            removeButtonEventHandlers.call(this);
+
+            this._aButtons = null;
+
+            var aForms = this.element.getElementsByTagName("form"),
+                oForm;
+
+            if (aForms.length > 0) {
+                oForm = aForms[0];
+
+                if (oForm) {
+                    Event.purgeElement(oForm);
+                    if (oForm.parentNode) {
+                        oForm.parentNode.removeChild(oForm);
+                    }
+                    this.form = null;
+                }
+            }
+            Dialog.superclass.destroy.call(this);
+        },
+
+        /**
+        * Returns a string representation of the object.
+        * @method toString
+        * @return {String} The string representation of the Dialog
+        */
+        toString: function () {
+            return "Dialog " + this.id;
+        }
+    
+    });
+
+}());
+
+(function () {
+
+    /**
+    * SimpleDialog is a simple implementation of Dialog that can be used to 
+    * submit a single value. Forms can be processed in 3 ways -- via an 
+    * asynchronous Connection utility call, a simple form POST or GET, 
+    * or manually.
+    * @namespace YAHOO.widget
+    * @class SimpleDialog
+    * @extends YAHOO.widget.Dialog
+    * @constructor
+    * @param {String} el The element ID representing the SimpleDialog 
+    * <em>OR</em>
+    * @param {HTMLElement} el The element representing the SimpleDialog
+    * @param {Object} userConfig The configuration object literal containing 
+    * the configuration that should be set for this SimpleDialog. See 
+    * configuration documentation for more details.
+    */
+    YAHOO.widget.SimpleDialog = function (el, userConfig) {
+    
+        YAHOO.widget.SimpleDialog.superclass.constructor.call(this, 
+            el, userConfig);
+    
+    };
+
+    var Dom = YAHOO.util.Dom,
+        SimpleDialog = YAHOO.widget.SimpleDialog,
+    
+        /**
+        * Constant representing the SimpleDialog's configuration properties
+        * @property DEFAULT_CONFIG
+        * @private
+        * @final
+        * @type Object
+        */
+        DEFAULT_CONFIG = {
+        
+            "ICON": { 
+                key: "icon", 
+                value: "none", 
+                suppressEvent: true  
+            },
+        
+            "TEXT": { 
+                key: "text", 
+                value: "", 
+                suppressEvent: true, 
+                supercedes: ["icon"] 
+            }
+        
+        };
+
+    /**
+    * Constant for the standard network icon for a blocking action
+    * @property YAHOO.widget.SimpleDialog.ICON_BLOCK
+    * @static
+    * @final
+    * @type String
+    */
+    SimpleDialog.ICON_BLOCK = "blckicon";
+    
+    /**
+    * Constant for the standard network icon for alarm
+    * @property YAHOO.widget.SimpleDialog.ICON_ALARM
+    * @static
+    * @final
+    * @type String
+    */
+    SimpleDialog.ICON_ALARM = "alrticon";
+    
+    /**
+    * Constant for the standard network icon for help
+    * @property YAHOO.widget.SimpleDialog.ICON_HELP
+    * @static
+    * @final
+    * @type String
+    */
+    SimpleDialog.ICON_HELP  = "hlpicon";
+    
+    /**
+    * Constant for the standard network icon for info
+    * @property YAHOO.widget.SimpleDialog.ICON_INFO
+    * @static
+    * @final
+    * @type String
+    */
+    SimpleDialog.ICON_INFO  = "infoicon";
+    
+    /**
+    * Constant for the standard network icon for warn
+    * @property YAHOO.widget.SimpleDialog.ICON_WARN
+    * @static
+    * @final
+    * @type String
+    */
+    SimpleDialog.ICON_WARN  = "warnicon";
+    
+    /**
+    * Constant for the standard network icon for a tip
+    * @property YAHOO.widget.SimpleDialog.ICON_TIP
+    * @static
+    * @final
+    * @type String
+    */
+    SimpleDialog.ICON_TIP   = "tipicon";
+
+    /**
+    * Constant representing the name of the CSS class applied to the element 
+    * created by the "icon" configuration property.
+    * @property YAHOO.widget.SimpleDialog.ICON_CSS_CLASSNAME
+    * @static
+    * @final
+    * @type String
+    */
+    SimpleDialog.ICON_CSS_CLASSNAME = "yui-icon";
+    
+    /**
+    * Constant representing the default CSS class used for a SimpleDialog
+    * @property YAHOO.widget.SimpleDialog.CSS_SIMPLEDIALOG
+    * @static
+    * @final
+    * @type String
+    */
+    SimpleDialog.CSS_SIMPLEDIALOG = "yui-simple-dialog";
+
+    
+    YAHOO.extend(SimpleDialog, YAHOO.widget.Dialog, {
+    
+        /**
+        * Initializes the class's configurable properties which can be changed 
+        * using the SimpleDialog's Config object (cfg).
+        * @method initDefaultConfig
+        */
+        initDefaultConfig: function () {
+        
+            SimpleDialog.superclass.initDefaultConfig.call(this);
+        
+            // Add dialog config properties //
+        
+            /**
+            * Sets the informational icon for the SimpleDialog
+            * @config icon
+            * @type String
+            * @default "none"
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.ICON.key, {
+                handler: this.configIcon,
+                value: DEFAULT_CONFIG.ICON.value,
+                suppressEvent: DEFAULT_CONFIG.ICON.suppressEvent
+            });
+        
+            /**
+            * Sets the text for the SimpleDialog
+            * @config text
+            * @type String
+            * @default ""
+            */
+            this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, { 
+                handler: this.configText, 
+                value: DEFAULT_CONFIG.TEXT.value, 
+                suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent, 
+                supercedes: DEFAULT_CONFIG.TEXT.supercedes 
+            });
+        
+        },
+        
+        
+        /**
+        * The SimpleDialog initialization method, which is executed for 
+        * SimpleDialog and all of its subclasses. This method is automatically 
+        * called by the constructor, and  sets up all DOM references for 
+        * pre-existing markup, and creates required markup if it is not 
+        * already present.
+        * @method init
+        * @param {String} el The element ID representing the SimpleDialog 
+        * <em>OR</em>
+        * @param {HTMLElement} el The element representing the SimpleDialog
+        * @param {Object} userConfig The configuration object literal 
+        * containing the configuration that should be set for this 
+        * SimpleDialog. See configuration documentation for more details.
+        */
+        init: function (el, userConfig) {
+
+            /*
+                Note that we don't pass the user config in here yet because we 
+                only want it executed once, at the lowest subclass level
+            */
+
+            SimpleDialog.superclass.init.call(this, el/*, userConfig*/);
+        
+            this.beforeInitEvent.fire(SimpleDialog);
+        
+            Dom.addClass(this.element, SimpleDialog.CSS_SIMPLEDIALOG);
+        
+            this.cfg.queueProperty("postmethod", "manual");
+        
+            if (userConfig) {
+                this.cfg.applyConfig(userConfig, true);
+            }
+        
+            this.beforeRenderEvent.subscribe(function () {
+                if (! this.body) {
+                    this.setBody("");
+                }
+            }, this, true);
+        
+            this.initEvent.fire(SimpleDialog);
+        
+        },
+        
+        /**
+        * Prepares the SimpleDialog's internal FORM object, creating one if one 
+        * is not currently present, and adding the value hidden field.
+        * @method registerForm
+        */
+        registerForm: function () {
+
+            SimpleDialog.superclass.registerForm.call(this);
+
+            this.form.innerHTML += "<input type=\"hidden\" name=\"" + 
+                this.id + "\" value=\"\"/>";
+
+        },
+        
+        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
+        
+        /**
+        * Fired when the "icon" property is set.
+        * @method configIcon
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configIcon: function (type,args,obj) {
+        
+            var sIcon = args[0],
+                oBody = this.body,
+                sCSSClass = SimpleDialog.ICON_CSS_CLASSNAME,
+                oIcon,
+                oIconParent;
+        
+            if (sIcon && sIcon != "none") {
+
+                oIcon = Dom.getElementsByClassName(sCSSClass, "*" , oBody);
+
+                if (oIcon) {
+
+                    oIconParent = oIcon.parentNode;
+                    
+                    if (oIconParent) {
+                    
+                        oIconParent.removeChild(oIcon);
+                        
+                        oIcon = null;
+                    
+                    }
+
+                }
+
+
+                if (sIcon.indexOf(".") == -1) {
+
+                    oIcon = document.createElement("span");
+                    oIcon.className = (sCSSClass + " " + sIcon);
+                    oIcon.innerHTML = "&#160;";
+
+                } else {
+
+                    oIcon = document.createElement("img");
+                    oIcon.src = (this.imageRoot + sIcon);
+                    oIcon.className = sCSSClass;
+
+                }
+                
+
+                if (oIcon) {
+                
+                    oBody.insertBefore(oIcon, oBody.firstChild);
+                
+                }
+
+            }
+
+        },
+
+        /**
+        * Fired when the "text" property is set.
+        * @method configText
+        * @param {String} type The CustomEvent type (usually the property name)
+        * @param {Object[]} args The CustomEvent arguments. For configuration 
+        * handlers, args[0] will equal the newly applied value for the property.
+        * @param {Object} obj The scope object. For configuration handlers, 
+        * this will usually equal the owner.
+        */
+        configText: function (type,args,obj) {
+            var text = args[0];
+            if (text) {
+                this.setBody(text);
+                this.cfg.refireEvent("icon");
+            }
+        },
+        
+        // END BUILT-IN PROPERTY EVENT HANDLERS //
+        
+        /**
+        * Returns a string representation of the object.
+        * @method toString
+        * @return {String} The string representation of the SimpleDialog
+        */
+        toString: function () {
+            return "SimpleDialog " + this.id;
+        }
+
+        /**
+        * <p>
+        * Sets the SimpleDialog's body content to the HTML specified. 
+        * If no body is present, one will be automatically created. 
+        * An empty string can be passed to the method to clear the contents of the body.
+        * </p>
+        * <p><strong>NOTE:</strong> SimpleDialog provides the <a href="#config_text">text</a>
+        * and <a href="#config_icon">icon</a> configuration properties to set the contents
+        * of it's body element in accordance with the UI design for a SimpleDialog (an 
+        * icon and message text). Calling setBody on the SimpleDialog will not enforce this 
+        * UI design constraint and will replace the entire contents of the SimpleDialog body. 
+        * It should only be used if you wish the replace the default icon/text body structure 
+        * of a SimpleDialog with your own custom markup.</p>
+        * 
+        * @method setBody
+        * @param {String} bodyContent The HTML used to set the body. 
+        * As a convenience, non HTMLElement objects can also be passed into 
+        * the method, and will be treated as strings, with the body innerHTML
+        * set to their default toString implementations.
+        * <em>OR</em>
+        * @param {HTMLElement} bodyContent The HTMLElement to add as the first and only child of the body element.
+        * <em>OR</em>
+        * @param {DocumentFragment} bodyContent The document fragment 
+        * containing elements which are to be added to the body
+        */
+    });
+
+}());
+
+(function () {
+
+    /**
+    * ContainerEffect encapsulates animation transitions that are executed when 
+    * an Overlay is shown or hidden.
+    * @namespace YAHOO.widget
+    * @class ContainerEffect
+    * @constructor
+    * @param {YAHOO.widget.Overlay} overlay The Overlay that the animation 
+    * should be associated with
+    * @param {Object} attrIn The object literal representing the animation 
+    * arguments to be used for the animate-in transition. The arguments for 
+    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
+    * duration(Number), and method(i.e. Easing.easeIn).
+    * @param {Object} attrOut The object literal representing the animation 
+    * arguments to be used for the animate-out transition. The arguments for  
+    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
+    * duration(Number), and method(i.e. Easing.easeIn).
+    * @param {HTMLElement} targetElement Optional. The target element that  
+    * should be animated during the transition. Defaults to overlay.element.
+    * @param {class} Optional. The animation class to instantiate. Defaults to 
+    * YAHOO.util.Anim. Other options include YAHOO.util.Motion.
+    */
+    YAHOO.widget.ContainerEffect = function (overlay, attrIn, attrOut, targetElement, animClass) {
+
+        if (!animClass) {
+            animClass = YAHOO.util.Anim;
+        }
+
+        /**
+        * The overlay to animate
+        * @property overlay
+        * @type YAHOO.widget.Overlay
+        */
+        this.overlay = overlay;
+    
+        /**
+        * The animation attributes to use when transitioning into view
+        * @property attrIn
+        * @type Object
+        */
+        this.attrIn = attrIn;
+    
+        /**
+        * The animation attributes to use when transitioning out of view
+        * @property attrOut
+        * @type Object
+        */
+        this.attrOut = attrOut;
+    
+        /**
+        * The target element to be animated
+        * @property targetElement
+        * @type HTMLElement
+        */
+        this.targetElement = targetElement || overlay.element;
+    
+        /**
+        * The animation class to use for animating the overlay
+        * @property animClass
+        * @type class
+        */
+        this.animClass = animClass;
+    
+    };
+
+
+    var Dom = YAHOO.util.Dom,
+        CustomEvent = YAHOO.util.CustomEvent,
+        ContainerEffect = YAHOO.widget.ContainerEffect;
+
+
+    /**
+    * A pre-configured ContainerEffect instance that can be used for fading 
+    * an overlay in and out.
+    * @method FADE
+    * @static
+    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
+    * @param {Number} dur The duration of the animation
+    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
+    */
+    ContainerEffect.FADE = function (overlay, dur) {
+
+        var Easing = YAHOO.util.Easing,
+            fin = {
+                attributes: {opacity:{from:0, to:1}},
+                duration: dur,
+                method: Easing.easeIn
+            },
+            fout = {
+                attributes: {opacity:{to:0}},
+                duration: dur,
+                method: Easing.easeOut
+            },
+            fade = new ContainerEffect(overlay, fin, fout, overlay.element);
+
+        fade.handleUnderlayStart = function() {
+            var underlay = this.overlay.underlay;
+            if (underlay && YAHOO.env.ua.ie) {
+                var hasFilters = (underlay.filters && underlay.filters.length > 0);
+                if(hasFilters) {
+                    Dom.addClass(overlay.element, "yui-effect-fade");
+                }
+            }
+        };
+
+        fade.handleUnderlayComplete = function() {
+            var underlay = this.overlay.underlay;
+            if (underlay && YAHOO.env.ua.ie) {
+                Dom.removeClass(overlay.element, "yui-effect-fade");
+            }
+        };
+
+        fade.handleStartAnimateIn = function (type, args, obj) {
+            Dom.addClass(obj.overlay.element, "hide-select");
+
+            if (!obj.overlay.underlay) {
+                obj.overlay.cfg.refireEvent("underlay");
+            }
+
+            obj.handleUnderlayStart();
+
+            obj.overlay._setDomVisibility(true);
+            Dom.setStyle(obj.overlay.element, "opacity", 0);
+        };
+
+        fade.handleCompleteAnimateIn = function (type,args,obj) {
+            Dom.removeClass(obj.overlay.element, "hide-select");
+
+            if (obj.overlay.element.style.filter) {
+                obj.overlay.element.style.filter = null;
+            }
+
+            obj.handleUnderlayComplete();
+
+            obj.overlay.cfg.refireEvent("iframe");
+            obj.animateInCompleteEvent.fire();
+        };
+
+        fade.handleStartAnimateOut = function (type, args, obj) {
+            Dom.addClass(obj.overlay.element, "hide-select");
+            obj.handleUnderlayStart();
+        };
+
+        fade.handleCompleteAnimateOut =  function (type, args, obj) {
+            Dom.removeClass(obj.overlay.element, "hide-select");
+            if (obj.overlay.element.style.filter) {
+                obj.overlay.element.style.filter = null;
+            }
+            obj.overlay._setDomVisibility(false);
+            Dom.setStyle(obj.overlay.element, "opacity", 1);
+
+            obj.handleUnderlayComplete();
+
+            obj.overlay.cfg.refireEvent("iframe");
+            obj.animateOutCompleteEvent.fire();
+        };
+
+        fade.init();
+        return fade;
+    };
+    
+    
+    /**
+    * A pre-configured ContainerEffect instance that can be used for sliding an 
+    * overlay in and out.
+    * @method SLIDE
+    * @static
+    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
+    * @param {Number} dur The duration of the animation
+    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
+    */
+    ContainerEffect.SLIDE = function (overlay, dur) {
+        var Easing = YAHOO.util.Easing,
+
+            x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
+            y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
+            clientWidth = Dom.getClientWidth(),
+            offsetWidth = overlay.element.offsetWidth,
+
+            sin =  { 
+                attributes: { points: { to: [x, y] } },
+                duration: dur,
+                method: Easing.easeIn 
+            },
+
+            sout = {
+                attributes: { points: { to: [(clientWidth + 25), y] } },
+                duration: dur,
+                method: Easing.easeOut 
+            },
+
+            slide = new ContainerEffect(overlay, sin, sout, overlay.element, YAHOO.util.Motion);
+
+        slide.handleStartAnimateIn = function (type,args,obj) {
+            obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
+            obj.overlay.element.style.top  = y + "px";
+        };
+
+        slide.handleTweenAnimateIn = function (type, args, obj) {
+        
+            var pos = Dom.getXY(obj.overlay.element),
+                currentX = pos[0],
+                currentY = pos[1];
+        
+            if (Dom.getStyle(obj.overlay.element, "visibility") == 
+                "hidden" && currentX < x) {
+
+                obj.overlay._setDomVisibility(true);
+
+            }
+        
+            obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
+            obj.overlay.cfg.refireEvent("iframe");
+        };
+        
+        slide.handleCompleteAnimateIn = function (type, args, obj) {
+            obj.overlay.cfg.setProperty("xy", [x, y], true);
+            obj.startX = x;
+            obj.startY = y;
+            obj.overlay.cfg.refireEvent("iframe");
+            obj.animateInCompleteEvent.fire();
+        };
+        
+        slide.handleStartAnimateOut = function (type, args, obj) {
+    
+            var vw = Dom.getViewportWidth(),
+                pos = Dom.getXY(obj.overlay.element),
+                yso = pos[1];
+    
+            obj.animOut.attributes.points.to = [(vw + 25), yso];
+        };
+        
+        slide.handleTweenAnimateOut = function (type, args, obj) {
+    
+            var pos = Dom.getXY(obj.overlay.element),
+                xto = pos[0],
+                yto = pos[1];
+        
+            obj.overlay.cfg.setProperty("xy", [xto, yto], true);
+            obj.overlay.cfg.refireEvent("iframe");
+        };
+        
+        slide.handleCompleteAnimateOut = function (type, args, obj) {
+            obj.overlay._setDomVisibility(false);
+
+            obj.overlay.cfg.setProperty("xy", [x, y]);
+            obj.animateOutCompleteEvent.fire();
+        };
+
+        slide.init();
+        return slide;
+    };
+
+    ContainerEffect.prototype = {
+
+        /**
+        * Initializes the animation classes and events.
+        * @method init
+        */
+        init: function () {
+
+            this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
+            this.beforeAnimateInEvent.signature = CustomEvent.LIST;
+            
+            this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
+            this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
+        
+            this.animateInCompleteEvent = this.createEvent("animateInComplete");
+            this.animateInCompleteEvent.signature = CustomEvent.LIST;
+        
+            this.animateOutCompleteEvent = 
+                this.createEvent("animateOutComplete");
+            this.animateOutCompleteEvent.signature = CustomEvent.LIST;
+        
+            this.animIn = new this.animClass(this.targetElement, 
+                this.attrIn.attributes, this.attrIn.duration, 
+                this.attrIn.method);
+
+            this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
+            this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
+
+            this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn, 
+                this);
+        
+            this.animOut = new this.animClass(this.targetElement, 
+                this.attrOut.attributes, this.attrOut.duration, 
+                this.attrOut.method);
+
+            this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
+            this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
+            this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut, 
+                this);
+
+        },
+        
+        /**
+        * Triggers the in-animation.
+        * @method animateIn
+        */
+        animateIn: function () {
+            this.beforeAnimateInEvent.fire();
+            this.animIn.animate();
+        },
+
+        /**
+        * Triggers the out-animation.
+        * @method animateOut
+        */
+        animateOut: function () {
+            this.beforeAnimateOutEvent.fire();
+            this.animOut.animate();
+        },
+
+        /**
+        * The default onStart handler for the in-animation.
+        * @method handleStartAnimateIn
+        * @param {String} type The CustomEvent type
+        * @param {Object[]} args The CustomEvent arguments
+        * @param {Object} obj The scope object
+        */
+        handleStartAnimateIn: function (type, args, obj) { },
+
+        /**
+        * The default onTween handler for the in-animation.
+        * @method handleTweenAnimateIn
+        * @param {String} type The CustomEvent type
+        * @param {Object[]} args The CustomEvent arguments
+        * @param {Object} obj The scope object
+        */
+        handleTweenAnimateIn: function (type, args, obj) { },
+
+        /**
+        * The default onComplete handler for the in-animation.
+        * @method handleCompleteAnimateIn
+        * @param {String} type The CustomEvent type
+        * @param {Object[]} args The CustomEvent arguments
+        * @param {Object} obj The scope object
+        */
+        handleCompleteAnimateIn: function (type, args, obj) { },
+
+        /**
+        * The default onStart handler for the out-animation.
+        * @method handleStartAnimateOut
+        * @param {String} type The CustomEvent type
+        * @param {Object[]} args The CustomEvent arguments
+        * @param {Object} obj The scope object
+        */
+        handleStartAnimateOut: function (type, args, obj) { },
+
+        /**
+        * The default onTween handler for the out-animation.
+        * @method handleTweenAnimateOut
+        * @param {String} type The CustomEvent type
+        * @param {Object[]} args The CustomEvent arguments
+        * @param {Object} obj The scope object
+        */
+        handleTweenAnimateOut: function (type, args, obj) { },
+
+        /**
+        * The default onComplete handler for the out-animation.
+        * @method handleCompleteAnimateOut
+        * @param {String} type The CustomEvent type
+        * @param {Object[]} args The CustomEvent arguments
+        * @param {Object} obj The scope object
+        */
+        handleCompleteAnimateOut: function (type, args, obj) { },
+        
+        /**
+        * Returns a string representation of the object.
+        * @method toString
+        * @return {String} The string representation of the ContainerEffect
+        */
+        toString: function () {
+            var output = "ContainerEffect";
+            if (this.overlay) {
+                output += " [" + this.overlay.toString() + "]";
+            }
+            return output;
+        }
+    };
+
+    YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
+
+})();
+
+YAHOO.register("container", YAHOO.widget.Module, {version: "2.7.0", build: "1799"});