You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by sn...@apache.org on 2009/09/28 04:57:47 UTC
svn commit: r819446 [15/28] - in /roller/trunk/apps/weblogger/web:
WEB-INF/jsps/editor/ WEB-INF/jsps/tiles/ roller-ui/yui/
roller-ui/yui/assets/ roller-ui/yui/assets/skins/
roller-ui/yui/assets/skins/sam/ roller-ui/yui/autocomplete/
roller-ui/yui/autoc...
Added: roller/trunk/apps/weblogger/web/roller-ui/yui/container/container.js
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/web/roller-ui/yui/container/container.js?rev=819446&view=auto
==============================================================================
--- roller/trunk/apps/weblogger/web/roller-ui/yui/container/container.js (added)
+++ roller/trunk/apps/weblogger/web/roller-ui/yui/container/container.js Mon Sep 28 02:57:43 2009
@@ -0,0 +1,9052 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.8.0r4
+*/
+(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} overrideContext 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, overrideContext) {
+
+ var property = this.config[key.toLowerCase()];
+
+ if (property && property.event) {
+ if (!Config.alreadySubscribed(property.event, handler, obj)) {
+ property.event.subscribe(handler, obj, overrideContext);
+ }
+ 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",
+ "DESTROY": "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.DESTROY);
+ 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 YUILibrary 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);
+ }
+
+ // Setting the background color fixes an issue with IE6/IE7, where
+ // elements in the DOM, with -ve margin-top which positioned them
+ // offscreen (so they would be overlapped by the iframe and its -ve top
+ // setting), would have their -ve margin-top ignored, when the iframe
+ // was added.
+ oIFrame.style.backgroundColor = "transparent";
+
+ oIFrame.style.borderWidth = "0";
+ oIFrame.style.width = "2em";
+ oIFrame.style.height = "2em";
+ oIFrame.style.left = "0";
+ oIFrame.style.top = (-1 * (oIFrame.offsetHeight + Module.RESIZE_MONITOR_BUFFER)) + "px";
+ oIFrame.style.visibility = "visible";
+
+ /*
+ Don't open/close the document for Gecko like we used to, since it
+ leads to duplicate cookies. (See YUILibrary 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;
+ }
+
+ if (this._rendered) {
+ this._renderHeader();
+ }
+
+ 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;
+ }
+
+ if (this._rendered) {
+ this._renderBody();
+ }
+
+ 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;
+ }
+
+ if (this._rendered) {
+ this._renderFooter();
+ }
+
+ 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;
+
+ 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;
+ }
+ }
+
+ this._renderHeader(moduleElement);
+ this._renderBody(moduleElement);
+ this._renderFooter(moduleElement);
+
+ this._rendered = true;
+
+ this.renderEvent.fire();
+ return true;
+ },
+
+ /**
+ * Renders the currently set header into it's proper position under the
+ * module element. If the module element is not provided, "this.element"
+ * is used.
+ *
+ * @method _renderHeader
+ * @protected
+ * @param {HTMLElement} moduleElement Optional. A reference to the module element
+ */
+ _renderHeader: function(moduleElement){
+ moduleElement = moduleElement || this.element;
+
+ // 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.
+ var firstChild = moduleElement.firstChild;
+ if (firstChild) {
+ moduleElement.insertBefore(this.header, firstChild);
+ } else {
+ moduleElement.appendChild(this.header);
+ }
+ }
+ },
+
+ /**
+ * Renders the currently set body into it's proper position under the
+ * module element. If the module element is not provided, "this.element"
+ * is used.
+ *
+ * @method _renderBody
+ * @protected
+ * @param {HTMLElement} moduleElement Optional. A reference to the module element.
+ */
+ _renderBody: function(moduleElement){
+ moduleElement = moduleElement || this.element;
+
+ 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(moduleElement, this.footer)) {
+ moduleElement.insertBefore(this.body, this.footer);
+ } else {
+ moduleElement.appendChild(this.body);
+ }
+ }
+ },
+
+ /**
+ * Renders the currently set footer into it's proper position under the
+ * module element. If the module element is not provided, "this.element"
+ * is used.
+ *
+ * @method _renderFooter
+ * @protected
+ * @param {HTMLElement} moduleElement Optional. A reference to the module element
+ */
+ _renderFooter: function(moduleElement){
+ moduleElement = moduleElement || this.element;
+
+ 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);
+ }
+ },
+
+ /**
+ * 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";
+
+ Overlay.PREVENT_OVERLAP_X = {
+ "tltr": true,
+ "blbr": true,
+ "brbl": true,
+ "trtl": true
+ };
+
+ Overlay.PREVENT_OVERLAP_Y = {
+ "trbr": true,
+ "tlbl": true,
+ "bltl": true,
+ "brtr": true
+ };
+
+ /**
+ * 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 default hidden CSS class used for an Overlay. This class is
+ * applied to the overlay's outer DIV whenever it's hidden.
+ *
+ * @property YAHOO.widget.Overlay.CSS_HIDDEN
+ * @static
+ * @final
+ * @type String
+ */
+ Overlay.CSS_HIDDEN = "yui-overlay-hidden";
+
+ /**
+ * Constant representing the default CSS class used for an Overlay iframe shim.
+ *
+ * @property YAHOO.widget.Overlay.CSS_IFRAME
+ * @static
+ * @final
+ * @type String
+ */
+ Overlay.CSS_IFRAME = "yui-overlay-iframe";
+
+ /**
+ * 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), xyOffset (optional)]</code>, the
+ * the 5 array elements described in detail below:
+ * </p>
+ *
+ * <dl>
+ * <dt>contextElementOrId <String|HTMLElement></dt>
+ * <dd>A reference to the context element to which the overlay should be aligned (or it's id).</dd>
+ * <dt>overlayCorner <String></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 <String></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) <Array[String|CustomEvent]></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>
+ * <dt>xyOffset <Number[]></dt>
+ * <dd>
+ * A 2 element Array specifying the X and Y pixel amounts by which the Overlay should be offset from the aligned corner. e.g. [5,0] offsets the Overlay 5 pixels to the left, <em>after</em> aligning the given context corners.
+ * NOTE: If using this property and no triggers need to be defined, the arrayOfTriggerEvents property should be set to null to maintain correct array positions for the arguments.
+ * </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>
+ * Setting this property to <code>["img1", "tl", "bl", null, [0,5]</code> will
+ * align the Overlay's top left corner to the bottom left corner of the
+ * context element with id "img1", and then offset it by 5 pixels on the Y axis (providing a 5 pixel gap between the bottom of the context element and top of the overlay).
+ * </p>
+ * <p>
+ * Adding the optional trigger values: <code>["img1", "tl", "bl", ["beforeShow", "windowResize"], [0,5]]</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
[... 6531 lines stripped ...]