PHP Classes

File: container_core.js

Recommend this page to a friend!
  Classes of Losev-Pahotin Ruslan  >  YahooUI-Menu  >  container_core.js  >  Download  
File: container_core.js
Role: Auxiliary data
Content type: text/plain
Description: YUI API
Class: YahooUI-Menu
Generate a menu from MySQL database data using YUI
Author: By
Last change:
Date: 15 years ago
Size: 139,782 bytes
 

Contents

Class file image Download
/* Copyright (c) 2007, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 2.3.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); } if (!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 = {}, prop, property; for (prop in this.config) { property = this.config[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, oValue, 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) { 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; 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, 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 } }; /** * 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;"; /** * 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"); 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 }); /** * Object or array of objects representing the ContainerEffect * classes that are active for animating the container. * @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 }); }, /** * 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. * @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, i, 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.element = el; if (el.id) { this.id = el.id; } child = this.element.firstChild; if (child) { do { switch (child.className) { case Module.CSS_HEADER: this.header = child; break; case Module.CSS_BODY: this.body = child; break; case Module.CSS_FOOTER: this.footer = child; break; } } 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); }, /** * Initialized an empty IFRAME that is placed out of the visible area * that can be used to detect text resize. * @method initResizeMonitor */ initResizeMonitor: function () { var oDoc, oIFrame, sHTML; function fireTextResize() { Module.textResizeEvent.fire(); } if (!YAHOO.env.ua.opera) { oIFrame = Dom.get("_yuiResizeMonitor"); if (!oIFrame) { oIFrame = document.createElement("iframe"); if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && YAHOO.env.ua.ie) { oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL; } /* Need to set "src" attribute of the iframe to prevent the browser from reporting duplicate cookies. (See SourceForge bug #1721755) */ if (YAHOO.env.ua.gecko) { sHTML = "<html><head><script " + "type=\"text/javascript\">" + "window.onresize=function(){window.parent." + "YAHOO.widget.Module.textResizeEvent." + "fire();};window.parent.YAHOO.widget.Module." + "textResizeEvent.fire();</script></head>" + "<body></body></html>"; oIFrame.src = "data:text/html;charset=utf-8," + encodeURIComponent(sHTML); } oIFrame.id = "_yuiResizeMonitor"; /* 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"; document.body.appendChild(oIFrame); oIFrame.style.width = "10em"; oIFrame.style.height = "10em"; oIFrame.style.top = (-1 * oIFrame.offsetHeight) + "px"; oIFrame.style.left = (-1 * oIFrame.offsetWidth) + "px"; oIFrame.style.borderWidth = "0"; oIFrame.style.visibility = "visible"; if (YAHOO.env.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 (!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; } } }, /** * 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 nLeft = -1 * this.resizeMonitor.offsetWidth, nTop = -1 * this.resizeMonitor.offsetHeight; this.resizeMonitor.style.top = nTop + "px"; this.resizeMonitor.style.left = nLeft + "px"; }, /** * Sets the Module's header content to the HTML specified, or appends * the passed element to the header. If no header is present, one will * be automatically created. * @method setHeader * @param {String} headerContent The HTML used to set the header * <em>OR</em> * @param {HTMLElement} headerContent The HTMLElement to append to * the header */ setHeader: function (headerContent) { var oHeader = this.header || (this.header = createHeader()); if (typeof headerContent == "string") { oHeader.innerHTML = headerContent; } else { oHeader.innerHTML = ""; oHeader.appendChild(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} element The element to append 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, or appends the * passed element to the body. If no body is present, one will be * automatically created. * @method setBody * @param {String} bodyContent The HTML used to set the body <em>OR</em> * @param {HTMLElement} bodyContent The HTMLElement to append to the body */ setBody: function (bodyContent) { var oBody = this.body || (this.body = createBody()); if (typeof bodyContent == "string") { oBody.innerHTML = bodyContent; } else { oBody.innerHTML = ""; oBody.appendChild(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} element The element to append 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. * @method setFooter * @param {String} footerContent The HTML used to set the footer * <em>OR</em> * @param {HTMLElement} footerContent The HTMLElement to append to * the footer */ setFooter: function (footerContent) { var oFooter = this.footer || (this.footer = createFooter()); if (typeof footerContent == "string") { oFooter.innerHTML = footerContent; } else { oFooter.innerHTML = ""; oFooter.appendChild(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} element The element to append 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. * NOTE: 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. * @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(element) { if (typeof element == "string") { element = document.getElementById(element); } if (element) { element.appendChild(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) { // Insert before first child if exists moduleElement.insertBefore(this.header, firstChild); } else { // Append to empty body because there are no children 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 */ // Insert before footer if exists in DOM if (this.footer && Dom.isAncestor( this.moduleElement, this.footer)) { moduleElement.insertBefore(this.body, this.footer); } else { // Append to element because there is no footer 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, e; 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(); for (e in this) { if (e instanceof CustomEvent) { e.unsubscribeAll(); } } }, /** * 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; } }, /** * 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 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, Overlay = YAHOO.widget.Overlay, 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, validator: Lang.isBoolean, supercedes: ["iframe", "visible"] }, "WIDTH": { key: "width", suppressEvent: true, supercedes: ["context", "fixedcenter", "iframe"] }, "HEIGHT": { key: "height", suppressEvent: true, supercedes: ["context", "fixedcenter", "iframe"] }, "ZINDEX": { key: "zindex", value: null }, "CONSTRAIN_TO_VIEWPORT": { key: "constraintoviewport", value: false, validator: Lang.isBoolean, supercedes: ["iframe", "x", "y", "xy"] }, "IFRAME": { key: "iframe", value: (YAHOO.env.ua.ie == 6 ? true : false), validator: Lang.isBoolean, supercedes: ["zindex"] } }; /** * 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. * @property YAHOO.widget.Overlay.IFRAME_SRC * @default 3 * @static * @final * @type Number */ Overlay.IFRAME_OFFSET = 3; /** * 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"; /** * 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) { if (YAHOO.env.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 (YAHOO.env.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; } YAHOO.extend(Overlay, Module, { /** * 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" && YAHOO.env.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); // Add overlay config properties // /** * The absolute x-coordinate position of the Overlay * @config x * @type Number * @default null */ this.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 */ this.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 */ this.cfg.addProperty(DEFAULT_CONFIG.XY.key, { handler: this.configXY, suppressEvent: DEFAULT_CONFIG.XY.suppressEvent, supercedes: DEFAULT_CONFIG.XY.supercedes }); /** * The array of context arguments for context-sensitive positioning. * The format is: [id or element, element corner, context corner]. * For example, setting this property to ["img1", "tl", "bl"] would * align the Overlay's top left corner to the context element's * bottom left corner. * @config context * @type Array * @default null */ this.cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, { handler: this.configContext, suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent, supercedes: DEFAULT_CONFIG.CONTEXT.supercedes }); /** * True if the Overlay should be anchored to the center of * the viewport. * @config fixedcenter * @type Boolean * @default false */ this.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 */ this.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 */ this.cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, { handler: this.configHeight, suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent, supercedes: DEFAULT_CONFIG.HEIGHT.supercedes }); /** * CSS z-index of the Overlay. * @config zIndex * @type Number * @default null */ this.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 */ this.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. */ this.cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, { handler: this.configIframe, value: DEFAULT_CONFIG.IFRAME.value, validator: DEFAULT_CONFIG.IFRAME.validator, supercedes: DEFAULT_CONFIG.IFRAME.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.removeClass(this.element, "show-scrollbars"); Dom.addClass(this.element, "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.removeClass(this.element, "hide-scrollbars"); Dom.addClass(this.element, "show-scrollbars"); }, // 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" && YAHOO.env.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(); Dom.setStyle(this.element, "visibility", "visible"); this.cfg.refireEvent("iframe"); this.showEvent.fire(); } } } 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 === "") { Dom.setStyle(this.element, "visibility", "hidden"); } } else { // Simple hide if (currentVis == "visible" || currentVis === "") { this.beforeHideEvent.fire(); Dom.setStyle(this.element, "visibility", "hidden"); this.hideEvent.fire(); } } } }, /** * Center event handler used for centering on scroll/resize, but only if * the Overlay is visible * @method doCenterOnDOMEvent */ doCenterOnDOMEvent: function () { if (this.cfg.getProperty("visible")) { this.center(); } }, /** * 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)) { 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 "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) { if (zIndex <= 0) { zIndex = 1; } Dom.setStyle(this.iframe, "zIndex", (zIndex - 1)); } Dom.setStyle(el, "zIndex", zIndex); this.cfg.setProperty("zIndex", zIndex, true); }, /** * 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) { oParentNode.appendChild(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)]); } }, /** * 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, aXY; 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 (YAHOO.env.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"; } oIFrame = m_oIFrameTemplate.cloneNode(false); oParent = oElement.parentNode; if (oParent) { oParent.appendChild(oIFrame); } else { document.body.appendChild(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(); // 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; } } }, /** * 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); } } else { 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; if (contextArgs) { contextEl = contextArgs[0]; elementMagnetCorner = contextArgs[1]; contextMagnetCorner = contextArgs[2]; if (contextEl) { if (typeof contextEl == "string") { this.cfg.setProperty("context", [document.getElementById(contextEl), elementMagnetCorner, contextMagnetCorner], true); } if (elementMagnetCorner && contextMagnetCorner) { this.align(elementMagnetCorner, contextMagnetCorner); } } } }, // 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], x = pos[0], y = pos[1], offsetHeight = this.element.offsetHeight, offsetWidth = this.element.offsetWidth, viewPortWidth = Dom.getViewportWidth(), viewPortHeight = Dom.getViewportHeight(), scrollX = Dom.getDocumentScrollLeft(), scrollY = Dom.getDocumentScrollTop(), topConstraint = scrollY + 10, leftConstraint = scrollX + 10, bottomConstraint = scrollY + viewPortHeight - offsetHeight - 10, rightConstraint = scrollX + viewPortWidth - offsetWidth - 10; if (x < leftConstraint) { x = leftConstraint; } else if (x > rightConstraint) { x = rightConstraint; } if (y < topConstraint) { y = topConstraint; } else if (y > bottomConstraint) { y = bottomConstraint; } this.cfg.setProperty("x", x, true); this.cfg.setProperty("y", y, true); this.cfg.setProperty("xy", [x, y], true); }, /** * Centers the container in the viewport. * @method center */ center: function () { var scrollX = Dom.getDocumentScrollLeft(), scrollY = Dom.getDocumentScrollTop(), viewPortWidth = Dom.getClientWidth(), viewPortHeight = Dom.getClientHeight(), elementWidth = this.element.offsetWidth, elementHeight = this.element.offsetHeight, x = (viewPortWidth / 2) - (elementWidth / 2) + scrollX, y = (viewPortHeight / 2) - (elementHeight / 2) + scrollY; this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]); this.cfg.refireEvent("iframe"); }, /** * 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); }, /** * 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 oOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY), Panel = YAHOO.widget.Panel; if (oOverlay && !Dom.isAncestor(oElement, oOverlay)) { 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) && oTopOverlay != oElement) { 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); Overlay.superclass.destroy.call(this); }, /** * 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) { if (activeOverlay != o) { if (activeOverlay) { activeOverlay.blur(); } this.bringToTop(o); activeOverlay = o; Dom.addClass(activeOverlay.element, OverlayManager.CSS_FOCUSED); o.focusEvent.fire(); } } }; /** * 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; } 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); if (o.element) { Event.removeListener(o.element, this.cfg.getProperty("focusevent"), this._onOverlayElementFocus); } o.cfg.setProperty("zIndex", originalZ, true); o.cfg.setProperty("manager", null); o.focusEvent.unsubscribeAll(); o.blurEvent.unsubscribeAll(); o.focusEvent = null; o.blurEvent = null; o.focus = null; 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--); } }; this._onOverlayBlur = function (p_sType, p_aArgs) { activeOverlay = null; }; 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 menu that * fired the event. */ _onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) { this.remove(p_oOverlay); }, /** * 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 mgr = this, zIndex, regcount, i, nOverlays; if (overlay instanceof Overlay) { overlay.cfg.addProperty("manager", { value: this } ); overlay.focusEvent = overlay.createEvent("focus"); overlay.focusEvent.signature = CustomEvent.LIST; overlay.blurEvent = overlay.createEvent("blur"); overlay.blurEvent.signature = CustomEvent.LIST; overlay.focus = function () { mgr.focus(this); }; overlay.blur = function () { if (mgr.getActive() == this) { Dom.removeClass(this.element, OverlayManager.CSS_FOCUSED); this.blurEvent.fire(); } }; overlay.blurEvent.subscribe(mgr._onOverlayBlur); overlay.hideEvent.subscribe(overlay.blur); overlay.destroyEvent.subscribe(this._onOverlayDestroy, overlay, this); Event.on(overlay.element, this.cfg.getProperty("focusevent"), this._onOverlayElementFocus, null, overlay); zIndex = Dom.getStyle(overlay.element, "zIndex"); if (!isNaN(zIndex)) { overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10)); } else { overlay.cfg.setProperty("zIndex", 0); } this.overlays.push(overlay); this.bringToTop(overlay); return true; } else if (overlay instanceof Array) { regcount = 0; nOverlays = overlay.length; for (i = 0; i < nOverlays; i++) { if (this.register(overlay[i])) { regcount++; } } if (regcount > 0) { return true; } } else { return false; } }, /** * 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) && oTopOverlay != oOverlay) { 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 aOverlays = this.overlays, nOverlays = aOverlays.length, i; if (nOverlays > 0) { i = nOverlays - 1; if (overlay instanceof Overlay) { do { if (aOverlays[i] == overlay) { return aOverlays[i]; } } while(i--); } else if (typeof overlay == "string") { do { if (aOverlays[i].id == overlay) { return aOverlays[i]; } } while(i--); } return null; } }, /** * 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.getProperty("zIndex"), zIndex2 = o2.cfg.getProperty("zIndex"); 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 aOverlays = this.overlays, nOverlays = aOverlays.length, i; if (nOverlays > 0) { i = nOverlays - 1; do { aOverlays[i].show(); } while(i--); } }, /** * Hides all Overlays in the manager. * @method hideAll */ hideAll: function () { var aOverlays = this.overlays, nOverlays = aOverlays.length, i; if (nOverlays > 0) { i = nOverlays - 1; do { aOverlays[i].hide(); } while(i--); } }, /** * Returns a string representation of the object. * @method toString * @return {String} The string representation of the OverlayManager */ toString: function () { return "OverlayManager"; } }; }()); (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, Easing = YAHOO.util.Easing, 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 fade = new ContainerEffect(overlay, { attributes: { opacity: { from: 0, to: 1 } }, duration: dur, method: Easing.easeIn }, { attributes: { opacity: { to: 0 } }, duration: dur, method: Easing.easeOut }, overlay.element); fade.handleStartAnimateIn = function (type,args,obj) { Dom.addClass(obj.overlay.element, "hide-select"); if (! obj.overlay.underlay) { obj.overlay.cfg.refireEvent("underlay"); } if (obj.overlay.underlay) { obj.initialUnderlayOpacity = Dom.getStyle(obj.overlay.underlay, "opacity"); obj.overlay.underlay.style.filter = null; } Dom.setStyle(obj.overlay.element, "visibility", "visible"); 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; } if (obj.overlay.underlay) { Dom.setStyle(obj.overlay.underlay, "opacity", obj.initialUnderlayOpacity); } obj.overlay.cfg.refireEvent("iframe"); obj.animateInCompleteEvent.fire(); }; fade.handleStartAnimateOut = function (type, args, obj) { Dom.addClass(obj.overlay.element, "hide-select"); if (obj.overlay.underlay) { obj.overlay.underlay.style.filter = null; } }; 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; } Dom.setStyle(obj.overlay.element, "visibility", "hidden"); Dom.setStyle(obj.overlay.element, "opacity", 1); 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 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, slide = new ContainerEffect(overlay, { attributes: { points: { to: [x, y] } }, duration: dur, method: Easing.easeIn }, { attributes: { points: { to: [(clientWidth + 25), y] } }, duration: dur, method: Easing.easeOut }, 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) { Dom.setStyle(obj.overlay.element, "visibility", "visible"); } 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], currentTo = obj.animOut.attributes.points.to; 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) { Dom.setStyle(obj.overlay.element, "visibility", "hidden"); 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_core", YAHOO.widget.Module, {version: "2.3.0", build: "442"});