MDL-11082 Improved groups upgrade performance 1.8x -> 1.9; thanks Eloy for telling...
[moodle-pu.git] / lib / yui / container / container_core.js
blob47d32703adfe8932a535e2a9679aaadd0b9de14d
1 /*
2 Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 2.3.0
6 */
7 (function () {
9 /**
10 * Config is a utility used within an Object to allow the implementer to
11 * maintain a list of local configuration properties and listen for changes
12 * to those properties dynamically using CustomEvent. The initial values are
13 * also maintained so that the configuration can be reset at any given point
14 * to its initial state.
15 * @namespace YAHOO.util
16 * @class Config
17 * @constructor
18 * @param {Object} owner The owner Object to which this Config Object belongs
20 YAHOO.util.Config = function (owner) {
22 if (owner) {
24 this.init(owner);
28 if (!owner) {
36 var Lang = YAHOO.lang,
37 CustomEvent = YAHOO.util.CustomEvent,
38 Config = YAHOO.util.Config;
41 /**
42 * Constant representing the CustomEvent type for the config changed event.
43 * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
44 * @private
45 * @static
46 * @final
48 Config.CONFIG_CHANGED_EVENT = "configChanged";
50 /**
51 * Constant representing the boolean type string
52 * @property YAHOO.util.Config.BOOLEAN_TYPE
53 * @private
54 * @static
55 * @final
57 Config.BOOLEAN_TYPE = "boolean";
59 Config.prototype = {
61 /**
62 * Object reference to the owner of this Config Object
63 * @property owner
64 * @type Object
66 owner: null,
68 /**
69 * Boolean flag that specifies whether a queue is currently
70 * being executed
71 * @property queueInProgress
72 * @type Boolean
74 queueInProgress: false,
76 /**
77 * Maintains the local collection of configuration property objects and
78 * their specified values
79 * @property config
80 * @private
81 * @type Object
82 */
83 config: null,
85 /**
86 * Maintains the local collection of configuration property objects as
87 * they were initially applied.
88 * This object is used when resetting a property.
89 * @property initialConfig
90 * @private
91 * @type Object
92 */
93 initialConfig: null,
95 /**
96 * Maintains the local, normalized CustomEvent queue
97 * @property eventQueue
98 * @private
99 * @type Object
101 eventQueue: null,
104 * Custom Event, notifying subscribers when Config properties are set
105 * (setProperty is called without the silent flag
106 * @event configChangedEvent
108 configChangedEvent: null,
111 * Initializes the configuration Object and all of its local members.
112 * @method init
113 * @param {Object} owner The owner Object to which this Config
114 * Object belongs
116 init: function (owner) {
118 this.owner = owner;
120 this.configChangedEvent =
121 this.createEvent(Config.CONFIG_CHANGED_EVENT);
123 this.configChangedEvent.signature = CustomEvent.LIST;
124 this.queueInProgress = false;
125 this.config = {};
126 this.initialConfig = {};
127 this.eventQueue = [];
132 * Validates that the value passed in is a Boolean.
133 * @method checkBoolean
134 * @param {Object} val The value to validate
135 * @return {Boolean} true, if the value is valid
137 checkBoolean: function (val) {
138 return (typeof val == Config.BOOLEAN_TYPE);
142 * Validates that the value passed in is a number.
143 * @method checkNumber
144 * @param {Object} val The value to validate
145 * @return {Boolean} true, if the value is valid
147 checkNumber: function (val) {
148 return (!isNaN(val));
152 * Fires a configuration property event using the specified value.
153 * @method fireEvent
154 * @private
155 * @param {String} key The configuration property's name
156 * @param {value} Object The value of the correct type for the property
158 fireEvent: function ( key, value ) {
159 var property = this.config[key];
161 if (property && property.event) {
162 property.event.fire(value);
167 * Adds a property to the Config Object's private config hash.
168 * @method addProperty
169 * @param {String} key The configuration property's name
170 * @param {Object} propertyObject The Object containing all of this
171 * property's arguments
173 addProperty: function ( key, propertyObject ) {
174 key = key.toLowerCase();
176 this.config[key] = propertyObject;
178 propertyObject.event = this.createEvent(key, { scope: this.owner });
179 propertyObject.event.signature = CustomEvent.LIST;
182 propertyObject.key = key;
184 if (propertyObject.handler) {
185 propertyObject.event.subscribe(propertyObject.handler,
186 this.owner);
189 this.setProperty(key, propertyObject.value, true);
191 if (! propertyObject.suppressEvent) {
192 this.queueProperty(key, propertyObject.value);
198 * Returns a key-value configuration map of the values currently set in
199 * the Config Object.
200 * @method getConfig
201 * @return {Object} The current config, represented in a key-value map
203 getConfig: function () {
205 var cfg = {},
206 prop,
207 property;
209 for (prop in this.config) {
210 property = this.config[prop];
211 if (property && property.event) {
212 cfg[prop] = property.value;
216 return cfg;
220 * Returns the value of specified property.
221 * @method getProperty
222 * @param {String} key The name of the property
223 * @return {Object} The value of the specified property
225 getProperty: function (key) {
226 var property = this.config[key.toLowerCase()];
227 if (property && property.event) {
228 return property.value;
229 } else {
230 return undefined;
235 * Resets the specified property's value to its initial value.
236 * @method resetProperty
237 * @param {String} key The name of the property
238 * @return {Boolean} True is the property was reset, false if not
240 resetProperty: function (key) {
242 key = key.toLowerCase();
244 var property = this.config[key];
246 if (property && property.event) {
248 if (this.initialConfig[key] &&
249 !Lang.isUndefined(this.initialConfig[key])) {
251 this.setProperty(key, this.initialConfig[key]);
253 return true;
257 } else {
259 return false;
265 * Sets the value of a property. If the silent property is passed as
266 * true, the property's event will not be fired.
267 * @method setProperty
268 * @param {String} key The name of the property
269 * @param {String} value The value to set the property to
270 * @param {Boolean} silent Whether the value should be set silently,
271 * without firing the property event.
272 * @return {Boolean} True, if the set was successful, false if it failed.
274 setProperty: function (key, value, silent) {
276 var property;
278 key = key.toLowerCase();
280 if (this.queueInProgress && ! silent) {
281 // Currently running through a queue...
282 this.queueProperty(key,value);
283 return true;
285 } else {
286 property = this.config[key];
287 if (property && property.event) {
288 if (property.validator && !property.validator(value)) {
289 return false;
290 } else {
291 property.value = value;
292 if (! silent) {
293 this.fireEvent(key, value);
294 this.configChangedEvent.fire([key, value]);
296 return true;
298 } else {
299 return false;
305 * Sets the value of a property and queues its event to execute. If the
306 * event is already scheduled to execute, it is
307 * moved from its current position to the end of the queue.
308 * @method queueProperty
309 * @param {String} key The name of the property
310 * @param {String} value The value to set the property to
311 * @return {Boolean} true, if the set was successful, false if
312 * it failed.
314 queueProperty: function (key, value) {
316 key = key.toLowerCase();
318 var property = this.config[key],
319 foundDuplicate = false,
320 iLen,
321 queueItem,
322 queueItemKey,
323 queueItemValue,
324 sLen,
325 supercedesCheck,
326 qLen,
327 queueItemCheck,
328 queueItemCheckKey,
329 queueItemCheckValue,
334 if (property && property.event) {
336 if (!Lang.isUndefined(value) && property.validator &&
337 !property.validator(value)) { // validator
338 return false;
339 } else {
341 if (!Lang.isUndefined(value)) {
342 property.value = value;
343 } else {
344 value = property.value;
347 foundDuplicate = false;
348 iLen = this.eventQueue.length;
350 for (i = 0; i < iLen; i++) {
351 queueItem = this.eventQueue[i];
353 if (queueItem) {
354 queueItemKey = queueItem[0];
355 queueItemValue = queueItem[1];
357 if (queueItemKey == key) {
360 found a dupe... push to end of queue, null
361 current item, and break
364 this.eventQueue[i] = null;
366 this.eventQueue.push(
367 [key, (!Lang.isUndefined(value) ?
368 value : queueItemValue)]);
370 foundDuplicate = true;
371 break;
376 // this is a refire, or a new property in the queue
378 if (! foundDuplicate && !Lang.isUndefined(value)) {
379 this.eventQueue.push([key, value]);
383 if (property.supercedes) {
385 sLen = property.supercedes.length;
387 for (s = 0; s < sLen; s++) {
389 supercedesCheck = property.supercedes[s];
390 qLen = this.eventQueue.length;
392 for (q = 0; q < qLen; q++) {
393 queueItemCheck = this.eventQueue[q];
395 if (queueItemCheck) {
396 queueItemCheckKey = queueItemCheck[0];
397 queueItemCheckValue = queueItemCheck[1];
399 if (queueItemCheckKey ==
400 supercedesCheck.toLowerCase() ) {
402 this.eventQueue.push([queueItemCheckKey,
403 queueItemCheckValue]);
405 this.eventQueue[q] = null;
406 break;
415 return true;
416 } else {
417 return false;
422 * Fires the event for a property using the property's current value.
423 * @method refireEvent
424 * @param {String} key The name of the property
426 refireEvent: function (key) {
428 key = key.toLowerCase();
430 var property = this.config[key];
432 if (property && property.event &&
434 !Lang.isUndefined(property.value)) {
436 if (this.queueInProgress) {
438 this.queueProperty(key);
440 } else {
442 this.fireEvent(key, property.value);
450 * Applies a key-value Object literal to the configuration, replacing
451 * any existing values, and queueing the property events.
452 * Although the values will be set, fireQueue() must be called for their
453 * associated events to execute.
454 * @method applyConfig
455 * @param {Object} userConfig The configuration Object literal
456 * @param {Boolean} init When set to true, the initialConfig will
457 * be set to the userConfig passed in, so that calling a reset will
458 * reset the properties to the passed values.
460 applyConfig: function (userConfig, init) {
462 var sKey,
463 oValue,
464 oConfig;
466 if (init) {
468 oConfig = {};
470 for (sKey in userConfig) {
472 if (Lang.hasOwnProperty(userConfig, sKey)) {
474 oConfig[sKey.toLowerCase()] = userConfig[sKey];
480 this.initialConfig = oConfig;
484 for (sKey in userConfig) {
486 if (Lang.hasOwnProperty(userConfig, sKey)) {
488 this.queueProperty(sKey, userConfig[sKey]);
497 * Refires the events for all configuration properties using their
498 * current values.
499 * @method refresh
501 refresh: function () {
503 var prop;
505 for (prop in this.config) {
506 this.refireEvent(prop);
511 * Fires the normalized list of queued property change events
512 * @method fireQueue
514 fireQueue: function () {
516 var i,
517 queueItem,
518 key,
519 value,
520 property;
522 this.queueInProgress = true;
523 for (i = 0;i < this.eventQueue.length; i++) {
524 queueItem = this.eventQueue[i];
525 if (queueItem) {
527 key = queueItem[0];
528 value = queueItem[1];
529 property = this.config[key];
531 property.value = value;
533 this.fireEvent(key,value);
537 this.queueInProgress = false;
538 this.eventQueue = [];
542 * Subscribes an external handler to the change event for any
543 * given property.
544 * @method subscribeToConfigEvent
545 * @param {String} key The property name
546 * @param {Function} handler The handler function to use subscribe to
547 * the property's event
548 * @param {Object} obj The Object to use for scoping the event handler
549 * (see CustomEvent documentation)
550 * @param {Boolean} override Optional. If true, will override "this"
551 * within the handler to map to the scope Object passed into the method.
552 * @return {Boolean} True, if the subscription was successful,
553 * otherwise false.
555 subscribeToConfigEvent: function (key, handler, obj, override) {
557 var property = this.config[key.toLowerCase()];
559 if (property && property.event) {
561 if (!Config.alreadySubscribed(property.event, handler, obj)) {
563 property.event.subscribe(handler, obj, override);
567 return true;
569 } else {
571 return false;
578 * Unsubscribes an external handler from the change event for any
579 * given property.
580 * @method unsubscribeFromConfigEvent
581 * @param {String} key The property name
582 * @param {Function} handler The handler function to use subscribe to
583 * the property's event
584 * @param {Object} obj The Object to use for scoping the event
585 * handler (see CustomEvent documentation)
586 * @return {Boolean} True, if the unsubscription was successful,
587 * otherwise false.
589 unsubscribeFromConfigEvent: function (key, handler, obj) {
590 var property = this.config[key.toLowerCase()];
591 if (property && property.event) {
592 return property.event.unsubscribe(handler, obj);
593 } else {
594 return false;
599 * Returns a string representation of the Config object
600 * @method toString
601 * @return {String} The Config object in string format.
603 toString: function () {
604 var output = "Config";
605 if (this.owner) {
606 output += " [" + this.owner.toString() + "]";
608 return output;
612 * Returns a string representation of the Config object's current
613 * CustomEvent queue
614 * @method outputEventQueue
615 * @return {String} The string list of CustomEvents currently queued
616 * for execution
618 outputEventQueue: function () {
620 var output = "",
621 queueItem,
623 nQueue = this.eventQueue.length;
625 for (q = 0; q < nQueue; q++) {
626 queueItem = this.eventQueue[q];
627 if (queueItem) {
628 output += queueItem[0] + "=" + queueItem[1] + ", ";
631 return output;
635 * Sets all properties to null, unsubscribes all listeners from each
636 * property's change event and all listeners from the configChangedEvent.
637 * @method destroy
639 destroy: function () {
641 var oConfig = this.config,
642 sProperty,
643 oProperty;
646 for (sProperty in oConfig) {
648 if (Lang.hasOwnProperty(oConfig, sProperty)) {
650 oProperty = oConfig[sProperty];
652 oProperty.event.unsubscribeAll();
653 oProperty.event = null;
659 this.configChangedEvent.unsubscribeAll();
661 this.configChangedEvent = null;
662 this.owner = null;
663 this.config = null;
664 this.initialConfig = null;
665 this.eventQueue = null;
674 * Checks to determine if a particular function/Object pair are already
675 * subscribed to the specified CustomEvent
676 * @method YAHOO.util.Config.alreadySubscribed
677 * @static
678 * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check
679 * the subscriptions
680 * @param {Function} fn The function to look for in the subscribers list
681 * @param {Object} obj The execution scope Object for the subscription
682 * @return {Boolean} true, if the function/Object pair is already subscribed
683 * to the CustomEvent passed in
685 Config.alreadySubscribed = function (evt, fn, obj) {
687 var nSubscribers = evt.subscribers.length,
688 subsc,
691 if (nSubscribers > 0) {
693 i = nSubscribers - 1;
695 do {
697 subsc = evt.subscribers[i];
699 if (subsc && subsc.obj == obj && subsc.fn == fn) {
701 return true;
706 while (i--);
710 return false;
714 YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
716 }());
717 (function () {
720 * The Container family of components is designed to enable developers to
721 * create different kinds of content-containing modules on the web. Module
722 * and Overlay are the most basic containers, and they can be used directly
723 * or extended to build custom containers. Also part of the Container family
724 * are four UI controls that extend Module and Overlay: Tooltip, Panel,
725 * Dialog, and SimpleDialog.
726 * @module container
727 * @title Container
728 * @requires yahoo, dom, event
729 * @optional dragdrop, animation, button
733 * Module is a JavaScript representation of the Standard Module Format.
734 * Standard Module Format is a simple standard for markup containers where
735 * child nodes representing the header, body, and footer of the content are
736 * denoted using the CSS classes "hd", "bd", and "ft" respectively.
737 * Module is the base class for all other classes in the YUI
738 * Container package.
739 * @namespace YAHOO.widget
740 * @class Module
741 * @constructor
742 * @param {String} el The element ID representing the Module <em>OR</em>
743 * @param {HTMLElement} el The element representing the Module
744 * @param {Object} userConfig The configuration Object literal containing
745 * the configuration that should be set for this module. See configuration
746 * documentation for more details.
748 YAHOO.widget.Module = function (el, userConfig) {
750 if (el) {
752 this.init(el, userConfig);
754 } else {
762 var Dom = YAHOO.util.Dom,
763 Config = YAHOO.util.Config,
764 Event = YAHOO.util.Event,
765 CustomEvent = YAHOO.util.CustomEvent,
766 Module = YAHOO.widget.Module,
768 m_oModuleTemplate,
769 m_oHeaderTemplate,
770 m_oBodyTemplate,
771 m_oFooterTemplate,
774 * Constant representing the name of the Module's events
775 * @property EVENT_TYPES
776 * @private
777 * @final
778 * @type Object
780 EVENT_TYPES = {
782 "BEFORE_INIT": "beforeInit",
783 "INIT": "init",
784 "APPEND": "append",
785 "BEFORE_RENDER": "beforeRender",
786 "RENDER": "render",
787 "CHANGE_HEADER": "changeHeader",
788 "CHANGE_BODY": "changeBody",
789 "CHANGE_FOOTER": "changeFooter",
790 "CHANGE_CONTENT": "changeContent",
791 "DESTORY": "destroy",
792 "BEFORE_SHOW": "beforeShow",
793 "SHOW": "show",
794 "BEFORE_HIDE": "beforeHide",
795 "HIDE": "hide"
800 * Constant representing the Module's configuration properties
801 * @property DEFAULT_CONFIG
802 * @private
803 * @final
804 * @type Object
806 DEFAULT_CONFIG = {
808 "VISIBLE": {
809 key: "visible",
810 value: true,
811 validator: YAHOO.lang.isBoolean
814 "EFFECT": {
815 key: "effect",
816 suppressEvent: true,
817 supercedes: ["visible"]
820 "MONITOR_RESIZE": {
821 key: "monitorresize",
822 value: true
829 * Constant representing the prefix path to use for non-secure images
830 * @property YAHOO.widget.Module.IMG_ROOT
831 * @static
832 * @final
833 * @type String
835 Module.IMG_ROOT = null;
838 * Constant representing the prefix path to use for securely served images
839 * @property YAHOO.widget.Module.IMG_ROOT_SSL
840 * @static
841 * @final
842 * @type String
844 Module.IMG_ROOT_SSL = null;
847 * Constant for the default CSS class name that represents a Module
848 * @property YAHOO.widget.Module.CSS_MODULE
849 * @static
850 * @final
851 * @type String
853 Module.CSS_MODULE = "yui-module";
856 * Constant representing the module header
857 * @property YAHOO.widget.Module.CSS_HEADER
858 * @static
859 * @final
860 * @type String
862 Module.CSS_HEADER = "hd";
865 * Constant representing the module body
866 * @property YAHOO.widget.Module.CSS_BODY
867 * @static
868 * @final
869 * @type String
871 Module.CSS_BODY = "bd";
874 * Constant representing the module footer
875 * @property YAHOO.widget.Module.CSS_FOOTER
876 * @static
877 * @final
878 * @type String
880 Module.CSS_FOOTER = "ft";
883 * Constant representing the url for the "src" attribute of the iframe
884 * used to monitor changes to the browser's base font size
885 * @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
886 * @static
887 * @final
888 * @type String
890 Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
893 * Singleton CustomEvent fired when the font size is changed in the browser.
894 * Opera's "zoom" functionality currently does not support text
895 * size detection.
896 * @event YAHOO.widget.Module.textResizeEvent
898 Module.textResizeEvent = new CustomEvent("textResize");
901 function createModuleTemplate() {
903 if (!m_oModuleTemplate) {
905 m_oModuleTemplate = document.createElement("div");
907 m_oModuleTemplate.innerHTML = ("<div class=\"" +
908 Module.CSS_HEADER + "\"></div>" + "<div class=\"" +
909 Module.CSS_BODY + "\"></div><div class=\"" +
910 Module.CSS_FOOTER + "\"></div>");
912 m_oHeaderTemplate = m_oModuleTemplate.firstChild;
913 m_oBodyTemplate = m_oHeaderTemplate.nextSibling;
914 m_oFooterTemplate = m_oBodyTemplate.nextSibling;
918 return m_oModuleTemplate;
923 function createHeader() {
925 if (!m_oHeaderTemplate) {
927 createModuleTemplate();
931 return (m_oHeaderTemplate.cloneNode(false));
936 function createBody() {
938 if (!m_oBodyTemplate) {
940 createModuleTemplate();
944 return (m_oBodyTemplate.cloneNode(false));
949 function createFooter() {
951 if (!m_oFooterTemplate) {
953 createModuleTemplate();
957 return (m_oFooterTemplate.cloneNode(false));
962 Module.prototype = {
965 * The class's constructor function
966 * @property contructor
967 * @type Function
969 constructor: Module,
972 * The main module element that contains the header, body, and footer
973 * @property element
974 * @type HTMLElement
976 element: null,
979 * The header element, denoted with CSS class "hd"
980 * @property header
981 * @type HTMLElement
983 header: null,
986 * The body element, denoted with CSS class "bd"
987 * @property body
988 * @type HTMLElement
990 body: null,
993 * The footer element, denoted with CSS class "ft"
994 * @property footer
995 * @type HTMLElement
997 footer: null,
1000 * The id of the element
1001 * @property id
1002 * @type String
1004 id: null,
1007 * A string representing the root path for all images created by
1008 * a Module instance.
1009 * @deprecated It is recommend that any images for a Module be applied
1010 * via CSS using the "background-image" property.
1011 * @property imageRoot
1012 * @type String
1014 imageRoot: Module.IMG_ROOT,
1017 * Initializes the custom events for Module which are fired
1018 * automatically at appropriate times by the Module class.
1019 * @method initEvents
1021 initEvents: function () {
1023 var SIGNATURE = CustomEvent.LIST;
1026 * CustomEvent fired prior to class initalization.
1027 * @event beforeInitEvent
1028 * @param {class} classRef class reference of the initializing
1029 * class, such as this.beforeInitEvent.fire(Module)
1031 this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT);
1032 this.beforeInitEvent.signature = SIGNATURE;
1035 * CustomEvent fired after class initalization.
1036 * @event initEvent
1037 * @param {class} classRef class reference of the initializing
1038 * class, such as this.beforeInitEvent.fire(Module)
1040 this.initEvent = this.createEvent(EVENT_TYPES.INIT);
1041 this.initEvent.signature = SIGNATURE;
1044 * CustomEvent fired when the Module is appended to the DOM
1045 * @event appendEvent
1047 this.appendEvent = this.createEvent(EVENT_TYPES.APPEND);
1048 this.appendEvent.signature = SIGNATURE;
1051 * CustomEvent fired before the Module is rendered
1052 * @event beforeRenderEvent
1054 this.beforeRenderEvent =
1055 this.createEvent(EVENT_TYPES.BEFORE_RENDER);
1056 this.beforeRenderEvent.signature = SIGNATURE;
1059 * CustomEvent fired after the Module is rendered
1060 * @event renderEvent
1062 this.renderEvent = this.createEvent(EVENT_TYPES.RENDER);
1063 this.renderEvent.signature = SIGNATURE;
1066 * CustomEvent fired when the header content of the Module
1067 * is modified
1068 * @event changeHeaderEvent
1069 * @param {String/HTMLElement} content String/element representing
1070 * the new header content
1072 this.changeHeaderEvent =
1073 this.createEvent(EVENT_TYPES.CHANGE_HEADER);
1074 this.changeHeaderEvent.signature = SIGNATURE;
1077 * CustomEvent fired when the body content of the Module is modified
1078 * @event changeBodyEvent
1079 * @param {String/HTMLElement} content String/element representing
1080 * the new body content
1082 this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY);
1083 this.changeBodyEvent.signature = SIGNATURE;
1086 * CustomEvent fired when the footer content of the Module
1087 * is modified
1088 * @event changeFooterEvent
1089 * @param {String/HTMLElement} content String/element representing
1090 * the new footer content
1092 this.changeFooterEvent =
1093 this.createEvent(EVENT_TYPES.CHANGE_FOOTER);
1094 this.changeFooterEvent.signature = SIGNATURE;
1097 * CustomEvent fired when the content of the Module is modified
1098 * @event changeContentEvent
1100 this.changeContentEvent =
1101 this.createEvent(EVENT_TYPES.CHANGE_CONTENT);
1102 this.changeContentEvent.signature = SIGNATURE;
1105 * CustomEvent fired when the Module is destroyed
1106 * @event destroyEvent
1108 this.destroyEvent = this.createEvent(EVENT_TYPES.DESTORY);
1109 this.destroyEvent.signature = SIGNATURE;
1112 * CustomEvent fired before the Module is shown
1113 * @event beforeShowEvent
1115 this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW);
1116 this.beforeShowEvent.signature = SIGNATURE;
1119 * CustomEvent fired after the Module is shown
1120 * @event showEvent
1122 this.showEvent = this.createEvent(EVENT_TYPES.SHOW);
1123 this.showEvent.signature = SIGNATURE;
1126 * CustomEvent fired before the Module is hidden
1127 * @event beforeHideEvent
1129 this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE);
1130 this.beforeHideEvent.signature = SIGNATURE;
1133 * CustomEvent fired after the Module is hidden
1134 * @event hideEvent
1136 this.hideEvent = this.createEvent(EVENT_TYPES.HIDE);
1137 this.hideEvent.signature = SIGNATURE;
1141 * String representing the current user-agent platform
1142 * @property platform
1143 * @type String
1145 platform: function () {
1147 var ua = navigator.userAgent.toLowerCase();
1149 if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
1151 return "windows";
1153 } else if (ua.indexOf("macintosh") != -1) {
1155 return "mac";
1157 } else {
1159 return false;
1163 }(),
1166 * String representing the user-agent of the browser
1167 * @deprecated Use YAHOO.env.ua
1168 * @property browser
1169 * @type String
1171 browser: function () {
1173 var ua = navigator.userAgent.toLowerCase();
1176 Check Opera first in case of spoof and check Safari before
1177 Gecko since Safari's user agent string includes "like Gecko"
1180 if (ua.indexOf('opera') != -1) {
1182 return 'opera';
1184 } else if (ua.indexOf('msie 7') != -1) {
1186 return 'ie7';
1188 } else if (ua.indexOf('msie') != -1) {
1190 return 'ie';
1192 } else if (ua.indexOf('safari') != -1) {
1194 return 'safari';
1196 } else if (ua.indexOf('gecko') != -1) {
1198 return 'gecko';
1200 } else {
1202 return false;
1206 }(),
1209 * Boolean representing whether or not the current browsing context is
1210 * secure (https)
1211 * @property isSecure
1212 * @type Boolean
1214 isSecure: function () {
1216 if (window.location.href.toLowerCase().indexOf("https") === 0) {
1218 return true;
1220 } else {
1222 return false;
1226 }(),
1229 * Initializes the custom events for Module which are fired
1230 * automatically at appropriate times by the Module class.
1232 initDefaultConfig: function () {
1234 // Add properties //
1237 * Specifies whether the Module is visible on the page.
1238 * @config visible
1239 * @type Boolean
1240 * @default true
1242 this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, {
1243 handler: this.configVisible,
1244 value: DEFAULT_CONFIG.VISIBLE.value,
1245 validator: DEFAULT_CONFIG.VISIBLE.validator
1249 * Object or array of objects representing the ContainerEffect
1250 * classes that are active for animating the container.
1251 * @config effect
1252 * @type Object
1253 * @default null
1255 this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, {
1256 suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent,
1257 supercedes: DEFAULT_CONFIG.EFFECT.supercedes
1261 * Specifies whether to create a special proxy iframe to monitor
1262 * for user font resizing in the document
1263 * @config monitorresize
1264 * @type Boolean
1265 * @default true
1267 this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, {
1268 handler: this.configMonitorResize,
1269 value: DEFAULT_CONFIG.MONITOR_RESIZE.value
1275 * The Module class's initialization method, which is executed for
1276 * Module and all of its subclasses. This method is automatically
1277 * called by the constructor, and sets up all DOM references for
1278 * pre-existing markup, and creates required markup if it is not
1279 * already present.
1280 * @method init
1281 * @param {String} el The element ID representing the Module <em>OR</em>
1282 * @param {HTMLElement} el The element representing the Module
1283 * @param {Object} userConfig The configuration Object literal
1284 * containing the configuration that should be set for this module.
1285 * See configuration documentation for more details.
1287 init: function (el, userConfig) {
1289 var elId, i, child;
1291 this.initEvents();
1293 this.beforeInitEvent.fire(Module);
1296 * The Module's Config object used for monitoring
1297 * configuration properties.
1298 * @property cfg
1299 * @type YAHOO.util.Config
1301 this.cfg = new Config(this);
1303 if (this.isSecure) {
1304 this.imageRoot = Module.IMG_ROOT_SSL;
1307 if (typeof el == "string") {
1309 elId = el;
1311 el = document.getElementById(el);
1313 if (! el) {
1315 el = (createModuleTemplate()).cloneNode(false);
1317 el.id = elId;
1323 this.element = el;
1325 if (el.id) {
1326 this.id = el.id;
1329 child = this.element.firstChild;
1331 if (child) {
1333 do {
1335 switch (child.className) {
1337 case Module.CSS_HEADER:
1339 this.header = child;
1341 break;
1343 case Module.CSS_BODY:
1345 this.body = child;
1347 break;
1349 case Module.CSS_FOOTER:
1351 this.footer = child;
1353 break;
1357 } while ((child = child.nextSibling));
1362 this.initDefaultConfig();
1364 Dom.addClass(this.element, Module.CSS_MODULE);
1366 if (userConfig) {
1367 this.cfg.applyConfig(userConfig, true);
1371 Subscribe to the fireQueue() method of Config so that any
1372 queued configuration changes are excecuted upon render of
1373 the Module
1376 if (!Config.alreadySubscribed(this.renderEvent,
1377 this.cfg.fireQueue, this.cfg)) {
1379 this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
1383 this.initEvent.fire(Module);
1387 * Initialized an empty IFRAME that is placed out of the visible area
1388 * that can be used to detect text resize.
1389 * @method initResizeMonitor
1391 initResizeMonitor: function () {
1393 var oDoc,
1394 oIFrame,
1395 sHTML;
1397 function fireTextResize() {
1399 Module.textResizeEvent.fire();
1403 if (!YAHOO.env.ua.opera) {
1405 oIFrame = Dom.get("_yuiResizeMonitor");
1407 if (!oIFrame) {
1409 oIFrame = document.createElement("iframe");
1411 if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL &&
1412 YAHOO.env.ua.ie) {
1414 oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL;
1420 Need to set "src" attribute of the iframe to
1421 prevent the browser from reporting duplicate
1422 cookies. (See SourceForge bug #1721755)
1425 if (YAHOO.env.ua.gecko) {
1427 sHTML = "<html><head><script " +
1428 "type=\"text/javascript\">" +
1429 "window.onresize=function(){window.parent." +
1430 "YAHOO.widget.Module.textResizeEvent." +
1431 "fire();};window.parent.YAHOO.widget.Module." +
1432 "textResizeEvent.fire();</script></head>" +
1433 "<body></body></html>";
1435 oIFrame.src = "data:text/html;charset=utf-8," +
1436 encodeURIComponent(sHTML);
1440 oIFrame.id = "_yuiResizeMonitor";
1443 Need to set "position" property before inserting the
1444 iframe into the document or Safari's status bar will
1445 forever indicate the iframe is loading
1446 (See SourceForge bug #1723064)
1449 oIFrame.style.position = "absolute";
1450 oIFrame.style.visibility = "hidden";
1452 document.body.appendChild(oIFrame);
1454 oIFrame.style.width = "10em";
1455 oIFrame.style.height = "10em";
1456 oIFrame.style.top = (-1 * oIFrame.offsetHeight) + "px";
1457 oIFrame.style.left = (-1 * oIFrame.offsetWidth) + "px";
1458 oIFrame.style.borderWidth = "0";
1459 oIFrame.style.visibility = "visible";
1461 if (YAHOO.env.ua.webkit) {
1463 oDoc = oIFrame.contentWindow.document;
1465 oDoc.open();
1466 oDoc.close();
1472 if (oIFrame && oIFrame.contentWindow) {
1474 Module.textResizeEvent.subscribe(this.onDomResize,
1475 this, true);
1477 if (!Module.textResizeInitialized) {
1479 if (!Event.on(oIFrame.contentWindow, "resize",
1480 fireTextResize)) {
1483 This will fail in IE if document.domain has
1484 changed, so we must change the listener to
1485 use the oIFrame element instead
1488 Event.on(oIFrame, "resize", fireTextResize);
1492 Module.textResizeInitialized = true;
1496 this.resizeMonitor = oIFrame;
1505 * Event handler fired when the resize monitor element is resized.
1506 * @method onDomResize
1507 * @param {DOMEvent} e The DOM resize event
1508 * @param {Object} obj The scope object passed to the handler
1510 onDomResize: function (e, obj) {
1512 var nLeft = -1 * this.resizeMonitor.offsetWidth,
1513 nTop = -1 * this.resizeMonitor.offsetHeight;
1515 this.resizeMonitor.style.top = nTop + "px";
1516 this.resizeMonitor.style.left = nLeft + "px";
1521 * Sets the Module's header content to the HTML specified, or appends
1522 * the passed element to the header. If no header is present, one will
1523 * be automatically created.
1524 * @method setHeader
1525 * @param {String} headerContent The HTML used to set the header
1526 * <em>OR</em>
1527 * @param {HTMLElement} headerContent The HTMLElement to append to
1528 * the header
1530 setHeader: function (headerContent) {
1532 var oHeader = this.header || (this.header = createHeader());
1534 if (typeof headerContent == "string") {
1536 oHeader.innerHTML = headerContent;
1538 } else {
1540 oHeader.innerHTML = "";
1541 oHeader.appendChild(headerContent);
1545 this.changeHeaderEvent.fire(headerContent);
1546 this.changeContentEvent.fire();
1551 * Appends the passed element to the header. If no header is present,
1552 * one will be automatically created.
1553 * @method appendToHeader
1554 * @param {HTMLElement} element The element to append to the header
1556 appendToHeader: function (element) {
1558 var oHeader = this.header || (this.header = createHeader());
1560 oHeader.appendChild(element);
1562 this.changeHeaderEvent.fire(element);
1563 this.changeContentEvent.fire();
1568 * Sets the Module's body content to the HTML specified, or appends the
1569 * passed element to the body. If no body is present, one will be
1570 * automatically created.
1571 * @method setBody
1572 * @param {String} bodyContent The HTML used to set the body <em>OR</em>
1573 * @param {HTMLElement} bodyContent The HTMLElement to append to the body
1575 setBody: function (bodyContent) {
1577 var oBody = this.body || (this.body = createBody());
1579 if (typeof bodyContent == "string") {
1581 oBody.innerHTML = bodyContent;
1583 } else {
1585 oBody.innerHTML = "";
1586 oBody.appendChild(bodyContent);
1590 this.changeBodyEvent.fire(bodyContent);
1591 this.changeContentEvent.fire();
1596 * Appends the passed element to the body. If no body is present, one
1597 * will be automatically created.
1598 * @method appendToBody
1599 * @param {HTMLElement} element The element to append to the body
1601 appendToBody: function (element) {
1603 var oBody = this.body || (this.body = createBody());
1605 oBody.appendChild(element);
1607 this.changeBodyEvent.fire(element);
1608 this.changeContentEvent.fire();
1613 * Sets the Module's footer content to the HTML specified, or appends
1614 * the passed element to the footer. If no footer is present, one will
1615 * be automatically created.
1616 * @method setFooter
1617 * @param {String} footerContent The HTML used to set the footer
1618 * <em>OR</em>
1619 * @param {HTMLElement} footerContent The HTMLElement to append to
1620 * the footer
1622 setFooter: function (footerContent) {
1624 var oFooter = this.footer || (this.footer = createFooter());
1626 if (typeof footerContent == "string") {
1628 oFooter.innerHTML = footerContent;
1630 } else {
1632 oFooter.innerHTML = "";
1633 oFooter.appendChild(footerContent);
1637 this.changeFooterEvent.fire(footerContent);
1638 this.changeContentEvent.fire();
1643 * Appends the passed element to the footer. If no footer is present,
1644 * one will be automatically created.
1645 * @method appendToFooter
1646 * @param {HTMLElement} element The element to append to the footer
1648 appendToFooter: function (element) {
1650 var oFooter = this.footer || (this.footer = createFooter());
1652 oFooter.appendChild(element);
1654 this.changeFooterEvent.fire(element);
1655 this.changeContentEvent.fire();
1660 * Renders the Module by inserting the elements that are not already
1661 * in the main Module into their correct places. Optionally appends
1662 * the Module to the specified node prior to the render's execution.
1663 * NOTE: For Modules without existing markup, the appendToNode argument
1664 * is REQUIRED. If this argument is ommitted and the current element is
1665 * not present in the document, the function will return false,
1666 * indicating that the render was a failure.
1667 * @method render
1668 * @param {String} appendToNode The element id to which the Module
1669 * should be appended to prior to rendering <em>OR</em>
1670 * @param {HTMLElement} appendToNode The element to which the Module
1671 * should be appended to prior to rendering
1672 * @param {HTMLElement} moduleElement OPTIONAL. The element that
1673 * represents the actual Standard Module container.
1674 * @return {Boolean} Success or failure of the render
1676 render: function (appendToNode, moduleElement) {
1678 var me = this,
1679 firstChild;
1681 function appendTo(element) {
1682 if (typeof element == "string") {
1683 element = document.getElementById(element);
1686 if (element) {
1687 element.appendChild(me.element);
1688 me.appendEvent.fire();
1692 this.beforeRenderEvent.fire();
1694 if (! moduleElement) {
1695 moduleElement = this.element;
1698 if (appendToNode) {
1700 appendTo(appendToNode);
1702 } else {
1705 No node was passed in. If the element is not already in
1706 the Dom, this fails
1709 if (! Dom.inDocument(this.element)) {
1712 return false;
1718 // Need to get everything into the DOM if it isn't already
1720 if (this.header && ! Dom.inDocument(this.header)) {
1723 There is a header, but it's not in the DOM yet...
1724 need to add it
1727 firstChild = moduleElement.firstChild;
1729 if (firstChild) { // Insert before first child if exists
1731 moduleElement.insertBefore(this.header, firstChild);
1733 } else { // Append to empty body because there are no children
1735 moduleElement.appendChild(this.header);
1741 if (this.body && ! Dom.inDocument(this.body)) {
1744 There is a body, but it's not in the DOM yet...
1745 need to add it
1749 // Insert before footer if exists in DOM
1751 if (this.footer && Dom.isAncestor(
1752 this.moduleElement, this.footer)) {
1754 moduleElement.insertBefore(this.body, this.footer);
1756 } else { // Append to element because there is no footer
1758 moduleElement.appendChild(this.body);
1764 if (this.footer && ! Dom.inDocument(this.footer)) {
1767 There is a footer, but it's not in the DOM yet...
1768 need to add it
1771 moduleElement.appendChild(this.footer);
1775 this.renderEvent.fire();
1776 return true;
1780 * Removes the Module element from the DOM and sets all child elements
1781 * to null.
1782 * @method destroy
1784 destroy: function () {
1786 var parent,
1789 if (this.element) {
1790 Event.purgeElement(this.element, true);
1791 parent = this.element.parentNode;
1794 if (parent) {
1795 parent.removeChild(this.element);
1798 this.element = null;
1799 this.header = null;
1800 this.body = null;
1801 this.footer = null;
1803 Module.textResizeEvent.unsubscribe(this.onDomResize, this);
1805 this.cfg.destroy();
1806 this.cfg = null;
1808 this.destroyEvent.fire();
1810 for (e in this) {
1811 if (e instanceof CustomEvent) {
1812 e.unsubscribeAll();
1819 * Shows the Module element by setting the visible configuration
1820 * property to true. Also fires two events: beforeShowEvent prior to
1821 * the visibility change, and showEvent after.
1822 * @method show
1824 show: function () {
1825 this.cfg.setProperty("visible", true);
1829 * Hides the Module element by setting the visible configuration
1830 * property to false. Also fires two events: beforeHideEvent prior to
1831 * the visibility change, and hideEvent after.
1832 * @method hide
1834 hide: function () {
1835 this.cfg.setProperty("visible", false);
1838 // BUILT-IN EVENT HANDLERS FOR MODULE //
1841 * Default event handler for changing the visibility property of a
1842 * Module. By default, this is achieved by switching the "display" style
1843 * between "block" and "none".
1844 * This method is responsible for firing showEvent and hideEvent.
1845 * @param {String} type The CustomEvent type (usually the property name)
1846 * @param {Object[]} args The CustomEvent arguments. For configuration
1847 * handlers, args[0] will equal the newly applied value for the property.
1848 * @param {Object} obj The scope object. For configuration handlers,
1849 * this will usually equal the owner.
1850 * @method configVisible
1852 configVisible: function (type, args, obj) {
1853 var visible = args[0];
1854 if (visible) {
1855 this.beforeShowEvent.fire();
1856 Dom.setStyle(this.element, "display", "block");
1857 this.showEvent.fire();
1858 } else {
1859 this.beforeHideEvent.fire();
1860 Dom.setStyle(this.element, "display", "none");
1861 this.hideEvent.fire();
1866 * Default event handler for the "monitorresize" configuration property
1867 * @param {String} type The CustomEvent type (usually the property name)
1868 * @param {Object[]} args The CustomEvent arguments. For configuration
1869 * handlers, args[0] will equal the newly applied value for the property.
1870 * @param {Object} obj The scope object. For configuration handlers,
1871 * this will usually equal the owner.
1872 * @method configMonitorResize
1874 configMonitorResize: function (type, args, obj) {
1876 var monitor = args[0];
1878 if (monitor) {
1880 this.initResizeMonitor();
1882 } else {
1884 Module.textResizeEvent.unsubscribe(
1885 this.onDomResize, this, true);
1887 this.resizeMonitor = null;
1893 * Returns a String representation of the Object.
1894 * @method toString
1895 * @return {String} The string representation of the Module
1897 toString: function () {
1898 return "Module " + this.id;
1903 YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
1905 }());
1906 (function () {
1909 * Overlay is a Module that is absolutely positioned above the page flow. It
1910 * has convenience methods for positioning and sizing, as well as options for
1911 * controlling zIndex and constraining the Overlay's position to the current
1912 * visible viewport. Overlay also contains a dynamicly generated IFRAME which
1913 * is placed beneath it for Internet Explorer 6 and 5.x so that it will be
1914 * properly rendered above SELECT elements.
1915 * @namespace YAHOO.widget
1916 * @class Overlay
1917 * @extends Module
1918 * @param {String} el The element ID representing the Overlay <em>OR</em>
1919 * @param {HTMLElement} el The element representing the Overlay
1920 * @param {Object} userConfig The configuration object literal containing
1921 * the configuration that should be set for this Overlay. See configuration
1922 * documentation for more details.
1923 * @constructor
1925 YAHOO.widget.Overlay = function (el, userConfig) {
1927 YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
1932 var Lang = YAHOO.lang,
1933 CustomEvent = YAHOO.util.CustomEvent,
1934 Module = YAHOO.widget.Module,
1935 Event = YAHOO.util.Event,
1936 Dom = YAHOO.util.Dom,
1937 Config = YAHOO.util.Config,
1938 Overlay = YAHOO.widget.Overlay,
1940 m_oIFrameTemplate,
1943 * Constant representing the name of the Overlay's events
1944 * @property EVENT_TYPES
1945 * @private
1946 * @final
1947 * @type Object
1949 EVENT_TYPES = {
1951 "BEFORE_MOVE": "beforeMove",
1952 "MOVE": "move"
1957 * Constant representing the Overlay's configuration properties
1958 * @property DEFAULT_CONFIG
1959 * @private
1960 * @final
1961 * @type Object
1963 DEFAULT_CONFIG = {
1965 "X": {
1966 key: "x",
1967 validator: Lang.isNumber,
1968 suppressEvent: true,
1969 supercedes: ["iframe"]
1972 "Y": {
1973 key: "y",
1974 validator: Lang.isNumber,
1975 suppressEvent: true,
1976 supercedes: ["iframe"]
1979 "XY": {
1980 key: "xy",
1981 suppressEvent: true,
1982 supercedes: ["iframe"]
1985 "CONTEXT": {
1986 key: "context",
1987 suppressEvent: true,
1988 supercedes: ["iframe"]
1991 "FIXED_CENTER": {
1992 key: "fixedcenter",
1993 value: false,
1994 validator: Lang.isBoolean,
1995 supercedes: ["iframe", "visible"]
1998 "WIDTH": {
1999 key: "width",
2000 suppressEvent: true,
2001 supercedes: ["context", "fixedcenter", "iframe"]
2004 "HEIGHT": {
2005 key: "height",
2006 suppressEvent: true,
2007 supercedes: ["context", "fixedcenter", "iframe"]
2010 "ZINDEX": {
2011 key: "zindex",
2012 value: null
2015 "CONSTRAIN_TO_VIEWPORT": {
2016 key: "constraintoviewport",
2017 value: false,
2018 validator: Lang.isBoolean,
2019 supercedes: ["iframe", "x", "y", "xy"]
2022 "IFRAME": {
2023 key: "iframe",
2024 value: (YAHOO.env.ua.ie == 6 ? true : false),
2025 validator: Lang.isBoolean,
2026 supercedes: ["zindex"]
2033 * The URL that will be placed in the iframe
2034 * @property YAHOO.widget.Overlay.IFRAME_SRC
2035 * @static
2036 * @final
2037 * @type String
2039 Overlay.IFRAME_SRC = "javascript:false;";
2042 * Number representing how much the iframe shim should be offset from each
2043 * side of an Overlay instance.
2044 * @property YAHOO.widget.Overlay.IFRAME_SRC
2045 * @default 3
2046 * @static
2047 * @final
2048 * @type Number
2050 Overlay.IFRAME_OFFSET = 3;
2053 * Constant representing the top left corner of an element, used for
2054 * configuring the context element alignment
2055 * @property YAHOO.widget.Overlay.TOP_LEFT
2056 * @static
2057 * @final
2058 * @type String
2060 Overlay.TOP_LEFT = "tl";
2063 * Constant representing the top right corner of an element, used for
2064 * configuring the context element alignment
2065 * @property YAHOO.widget.Overlay.TOP_RIGHT
2066 * @static
2067 * @final
2068 * @type String
2070 Overlay.TOP_RIGHT = "tr";
2073 * Constant representing the top bottom left corner of an element, used for
2074 * configuring the context element alignment
2075 * @property YAHOO.widget.Overlay.BOTTOM_LEFT
2076 * @static
2077 * @final
2078 * @type String
2080 Overlay.BOTTOM_LEFT = "bl";
2083 * Constant representing the bottom right corner of an element, used for
2084 * configuring the context element alignment
2085 * @property YAHOO.widget.Overlay.BOTTOM_RIGHT
2086 * @static
2087 * @final
2088 * @type String
2090 Overlay.BOTTOM_RIGHT = "br";
2093 * Constant representing the default CSS class used for an Overlay
2094 * @property YAHOO.widget.Overlay.CSS_OVERLAY
2095 * @static
2096 * @final
2097 * @type String
2099 Overlay.CSS_OVERLAY = "yui-overlay";
2103 * A singleton CustomEvent used for reacting to the DOM event for
2104 * window scroll
2105 * @event YAHOO.widget.Overlay.windowScrollEvent
2107 Overlay.windowScrollEvent = new CustomEvent("windowScroll");
2110 * A singleton CustomEvent used for reacting to the DOM event for
2111 * window resize
2112 * @event YAHOO.widget.Overlay.windowResizeEvent
2114 Overlay.windowResizeEvent = new CustomEvent("windowResize");
2117 * The DOM event handler used to fire the CustomEvent for window scroll
2118 * @method YAHOO.widget.Overlay.windowScrollHandler
2119 * @static
2120 * @param {DOMEvent} e The DOM scroll event
2122 Overlay.windowScrollHandler = function (e) {
2124 if (YAHOO.env.ua.ie) {
2126 if (! window.scrollEnd) {
2128 window.scrollEnd = -1;
2132 clearTimeout(window.scrollEnd);
2134 window.scrollEnd = setTimeout(function () {
2136 Overlay.windowScrollEvent.fire();
2138 }, 1);
2140 } else {
2142 Overlay.windowScrollEvent.fire();
2149 * The DOM event handler used to fire the CustomEvent for window resize
2150 * @method YAHOO.widget.Overlay.windowResizeHandler
2151 * @static
2152 * @param {DOMEvent} e The DOM resize event
2154 Overlay.windowResizeHandler = function (e) {
2156 if (YAHOO.env.ua.ie) {
2158 if (! window.resizeEnd) {
2159 window.resizeEnd = -1;
2162 clearTimeout(window.resizeEnd);
2164 window.resizeEnd = setTimeout(function () {
2166 Overlay.windowResizeEvent.fire();
2168 }, 100);
2170 } else {
2172 Overlay.windowResizeEvent.fire();
2179 * A boolean that indicated whether the window resize and scroll events have
2180 * already been subscribed to.
2181 * @property YAHOO.widget.Overlay._initialized
2182 * @private
2183 * @type Boolean
2185 Overlay._initialized = null;
2187 if (Overlay._initialized === null) {
2189 Event.on(window, "scroll", Overlay.windowScrollHandler);
2190 Event.on(window, "resize", Overlay.windowResizeHandler);
2192 Overlay._initialized = true;
2196 YAHOO.extend(Overlay, Module, {
2199 * The Overlay initialization method, which is executed for Overlay and
2200 * all of its subclasses. This method is automatically called by the
2201 * constructor, and sets up all DOM references for pre-existing markup,
2202 * and creates required markup if it is not already present.
2203 * @method init
2204 * @param {String} el The element ID representing the Overlay <em>OR</em>
2205 * @param {HTMLElement} el The element representing the Overlay
2206 * @param {Object} userConfig The configuration object literal
2207 * containing the configuration that should be set for this Overlay.
2208 * See configuration documentation for more details.
2210 init: function (el, userConfig) {
2213 Note that we don't pass the user config in here yet because we
2214 only want it executed once, at the lowest subclass level
2217 Overlay.superclass.init.call(this, el/*, userConfig*/);
2219 this.beforeInitEvent.fire(Overlay);
2221 Dom.addClass(this.element, Overlay.CSS_OVERLAY);
2223 if (userConfig) {
2225 this.cfg.applyConfig(userConfig, true);
2229 if (this.platform == "mac" && YAHOO.env.ua.gecko) {
2231 if (! Config.alreadySubscribed(this.showEvent,
2232 this.showMacGeckoScrollbars, this)) {
2234 this.showEvent.subscribe(this.showMacGeckoScrollbars,
2235 this, true);
2239 if (! Config.alreadySubscribed(this.hideEvent,
2240 this.hideMacGeckoScrollbars, this)) {
2242 this.hideEvent.subscribe(this.hideMacGeckoScrollbars,
2243 this, true);
2249 this.initEvent.fire(Overlay);
2254 * Initializes the custom events for Overlay which are fired
2255 * automatically at appropriate times by the Overlay class.
2256 * @method initEvents
2258 initEvents: function () {
2260 Overlay.superclass.initEvents.call(this);
2262 var SIGNATURE = CustomEvent.LIST;
2265 * CustomEvent fired before the Overlay is moved.
2266 * @event beforeMoveEvent
2267 * @param {Number} x x coordinate
2268 * @param {Number} y y coordinate
2270 this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
2271 this.beforeMoveEvent.signature = SIGNATURE;
2274 * CustomEvent fired after the Overlay is moved.
2275 * @event moveEvent
2276 * @param {Number} x x coordinate
2277 * @param {Number} y y coordinate
2279 this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
2280 this.moveEvent.signature = SIGNATURE;
2285 * Initializes the class's configurable properties which can be changed
2286 * using the Overlay's Config object (cfg).
2287 * @method initDefaultConfig
2289 initDefaultConfig: function () {
2291 Overlay.superclass.initDefaultConfig.call(this);
2294 // Add overlay config properties //
2297 * The absolute x-coordinate position of the Overlay
2298 * @config x
2299 * @type Number
2300 * @default null
2302 this.cfg.addProperty(DEFAULT_CONFIG.X.key, {
2304 handler: this.configX,
2305 validator: DEFAULT_CONFIG.X.validator,
2306 suppressEvent: DEFAULT_CONFIG.X.suppressEvent,
2307 supercedes: DEFAULT_CONFIG.X.supercedes
2313 * The absolute y-coordinate position of the Overlay
2314 * @config y
2315 * @type Number
2316 * @default null
2318 this.cfg.addProperty(DEFAULT_CONFIG.Y.key, {
2320 handler: this.configY,
2321 validator: DEFAULT_CONFIG.Y.validator,
2322 suppressEvent: DEFAULT_CONFIG.Y.suppressEvent,
2323 supercedes: DEFAULT_CONFIG.Y.supercedes
2329 * An array with the absolute x and y positions of the Overlay
2330 * @config xy
2331 * @type Number[]
2332 * @default null
2334 this.cfg.addProperty(DEFAULT_CONFIG.XY.key, {
2336 handler: this.configXY,
2337 suppressEvent: DEFAULT_CONFIG.XY.suppressEvent,
2338 supercedes: DEFAULT_CONFIG.XY.supercedes
2344 * The array of context arguments for context-sensitive positioning.
2345 * The format is: [id or element, element corner, context corner].
2346 * For example, setting this property to ["img1", "tl", "bl"] would
2347 * align the Overlay's top left corner to the context element's
2348 * bottom left corner.
2349 * @config context
2350 * @type Array
2351 * @default null
2353 this.cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
2355 handler: this.configContext,
2356 suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent,
2357 supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
2363 * True if the Overlay should be anchored to the center of
2364 * the viewport.
2365 * @config fixedcenter
2366 * @type Boolean
2367 * @default false
2369 this.cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
2371 handler: this.configFixedCenter,
2372 value: DEFAULT_CONFIG.FIXED_CENTER.value,
2373 validator: DEFAULT_CONFIG.FIXED_CENTER.validator,
2374 supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
2380 * CSS width of the Overlay.
2381 * @config width
2382 * @type String
2383 * @default null
2385 this.cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
2387 handler: this.configWidth,
2388 suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent,
2389 supercedes: DEFAULT_CONFIG.WIDTH.supercedes
2394 * CSS height of the Overlay.
2395 * @config height
2396 * @type String
2397 * @default null
2399 this.cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
2401 handler: this.configHeight,
2402 suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent,
2403 supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
2408 * CSS z-index of the Overlay.
2409 * @config zIndex
2410 * @type Number
2411 * @default null
2413 this.cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
2415 handler: this.configzIndex,
2416 value: DEFAULT_CONFIG.ZINDEX.value
2421 * True if the Overlay should be prevented from being positioned
2422 * out of the viewport.
2423 * @config constraintoviewport
2424 * @type Boolean
2425 * @default false
2427 this.cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
2429 handler: this.configConstrainToViewport,
2430 value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value,
2431 validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator,
2432 supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
2437 * @config iframe
2438 * @description Boolean indicating whether or not the Overlay should
2439 * have an IFRAME shim; used to prevent <SELECT> elements from
2440 * poking through an Overlay instance in IE6. When set to "true",
2441 * the iframe shim is created when the Overlay instance is intially
2442 * made visible.
2443 * @type Boolean
2444 * @default true for IE6 and below, false for all other browsers.
2446 this.cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
2448 handler: this.configIframe,
2449 value: DEFAULT_CONFIG.IFRAME.value,
2450 validator: DEFAULT_CONFIG.IFRAME.validator,
2451 supercedes: DEFAULT_CONFIG.IFRAME.supercedes
2458 * Moves the Overlay to the specified position. This function is
2459 * identical to calling this.cfg.setProperty("xy", [x,y]);
2460 * @method moveTo
2461 * @param {Number} x The Overlay's new x position
2462 * @param {Number} y The Overlay's new y position
2464 moveTo: function (x, y) {
2466 this.cfg.setProperty("xy", [x, y]);
2471 * Adds a CSS class ("hide-scrollbars") and removes a CSS class
2472 * ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X
2473 * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2474 * @method hideMacGeckoScrollbars
2476 hideMacGeckoScrollbars: function () {
2478 Dom.removeClass(this.element, "show-scrollbars");
2479 Dom.addClass(this.element, "hide-scrollbars");
2484 * Adds a CSS class ("show-scrollbars") and removes a CSS class
2485 * ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X
2486 * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2487 * @method showMacGeckoScrollbars
2489 showMacGeckoScrollbars: function () {
2491 Dom.removeClass(this.element, "hide-scrollbars");
2492 Dom.addClass(this.element, "show-scrollbars");
2496 // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
2499 * The default event handler fired when the "visible" property is
2500 * changed. This method is responsible for firing showEvent
2501 * and hideEvent.
2502 * @method configVisible
2503 * @param {String} type The CustomEvent type (usually the property name)
2504 * @param {Object[]} args The CustomEvent arguments. For configuration
2505 * handlers, args[0] will equal the newly applied value for the property.
2506 * @param {Object} obj The scope object. For configuration handlers,
2507 * this will usually equal the owner.
2509 configVisible: function (type, args, obj) {
2511 var visible = args[0],
2512 currentVis = Dom.getStyle(this.element, "visibility"),
2513 effect = this.cfg.getProperty("effect"),
2514 effectInstances = [],
2515 isMacGecko = (this.platform == "mac" && YAHOO.env.ua.gecko),
2516 alreadySubscribed = Config.alreadySubscribed,
2517 eff, ei, e, i, j, k, h,
2518 nEffects,
2519 nEffectInstances;
2522 if (currentVis == "inherit") {
2524 e = this.element.parentNode;
2526 while (e.nodeType != 9 && e.nodeType != 11) {
2528 currentVis = Dom.getStyle(e, "visibility");
2530 if (currentVis != "inherit") {
2532 break;
2536 e = e.parentNode;
2540 if (currentVis == "inherit") {
2542 currentVis = "visible";
2549 if (effect) {
2551 if (effect instanceof Array) {
2553 nEffects = effect.length;
2555 for (i = 0; i < nEffects; i++) {
2557 eff = effect[i];
2559 effectInstances[effectInstances.length] =
2560 eff.effect(this, eff.duration);
2564 } else {
2566 effectInstances[effectInstances.length] =
2567 effect.effect(this, effect.duration);
2574 if (visible) { // Show
2576 if (isMacGecko) {
2578 this.showMacGeckoScrollbars();
2583 if (effect) { // Animate in
2586 if (visible) { // Animate in if not showing
2589 if (currentVis != "visible" || currentVis === "") {
2591 this.beforeShowEvent.fire();
2593 nEffectInstances = effectInstances.length;
2595 for (j = 0; j < nEffectInstances; j++) {
2597 ei = effectInstances[j];
2599 if (j === 0 && !alreadySubscribed(
2600 ei.animateInCompleteEvent,
2601 this.showEvent.fire, this.showEvent)) {
2604 Delegate showEvent until end
2605 of animateInComplete
2608 ei.animateInCompleteEvent.subscribe(
2609 this.showEvent.fire, this.showEvent, true);
2613 ei.animateIn();
2621 } else { // Show
2623 if (currentVis != "visible" || currentVis === "") {
2625 this.beforeShowEvent.fire();
2627 Dom.setStyle(this.element, "visibility", "visible");
2629 this.cfg.refireEvent("iframe");
2630 this.showEvent.fire();
2636 } else { // Hide
2638 if (isMacGecko) {
2640 this.hideMacGeckoScrollbars();
2644 if (effect) { // Animate out if showing
2646 if (currentVis == "visible") {
2648 this.beforeHideEvent.fire();
2650 nEffectInstances = effectInstances.length;
2652 for (k = 0; k < nEffectInstances; k++) {
2654 h = effectInstances[k];
2656 if (k === 0 && !alreadySubscribed(
2657 h.animateOutCompleteEvent, this.hideEvent.fire,
2658 this.hideEvent)) {
2661 Delegate hideEvent until end
2662 of animateOutComplete
2665 h.animateOutCompleteEvent.subscribe(
2666 this.hideEvent.fire, this.hideEvent, true);
2670 h.animateOut();
2674 } else if (currentVis === "") {
2676 Dom.setStyle(this.element, "visibility", "hidden");
2680 } else { // Simple hide
2682 if (currentVis == "visible" || currentVis === "") {
2684 this.beforeHideEvent.fire();
2686 Dom.setStyle(this.element, "visibility", "hidden");
2688 this.hideEvent.fire();
2699 * Center event handler used for centering on scroll/resize, but only if
2700 * the Overlay is visible
2701 * @method doCenterOnDOMEvent
2703 doCenterOnDOMEvent: function () {
2705 if (this.cfg.getProperty("visible")) {
2707 this.center();
2714 * The default event handler fired when the "fixedcenter" property
2715 * is changed.
2716 * @method configFixedCenter
2717 * @param {String} type The CustomEvent type (usually the property name)
2718 * @param {Object[]} args The CustomEvent arguments. For configuration
2719 * handlers, args[0] will equal the newly applied value for the property.
2720 * @param {Object} obj The scope object. For configuration handlers,
2721 * this will usually equal the owner.
2723 configFixedCenter: function (type, args, obj) {
2725 var val = args[0],
2726 alreadySubscribed = Config.alreadySubscribed,
2727 windowResizeEvent = Overlay.windowResizeEvent,
2728 windowScrollEvent = Overlay.windowScrollEvent;
2730 if (val) {
2732 this.center();
2734 if (!alreadySubscribed(this.beforeShowEvent,
2735 this.center, this)) {
2737 this.beforeShowEvent.subscribe(this.center);
2741 if (!alreadySubscribed(windowResizeEvent,
2742 this.doCenterOnDOMEvent, this)) {
2744 windowResizeEvent.subscribe(this.doCenterOnDOMEvent,
2745 this, true);
2749 if (!alreadySubscribed(windowScrollEvent,
2750 this.doCenterOnDOMEvent, this)) {
2752 windowScrollEvent.subscribe(this.doCenterOnDOMEvent,
2753 this, true);
2757 } else {
2759 this.beforeShowEvent.unsubscribe(this.center);
2761 windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2762 windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2769 * The default event handler fired when the "height" property is changed.
2770 * @method configHeight
2771 * @param {String} type The CustomEvent type (usually the property name)
2772 * @param {Object[]} args The CustomEvent arguments. For configuration
2773 * handlers, args[0] will equal the newly applied value for the property.
2774 * @param {Object} obj The scope object. For configuration handlers,
2775 * this will usually equal the owner.
2777 configHeight: function (type, args, obj) {
2779 var height = args[0],
2780 el = this.element;
2782 Dom.setStyle(el, "height", height);
2783 this.cfg.refireEvent("iframe");
2788 * The default event handler fired when the "width" property is changed.
2789 * @method configWidth
2790 * @param {String} type The CustomEvent type (usually the property name)
2791 * @param {Object[]} args The CustomEvent arguments. For configuration
2792 * handlers, args[0] will equal the newly applied value for the property.
2793 * @param {Object} obj The scope object. For configuration handlers,
2794 * this will usually equal the owner.
2796 configWidth: function (type, args, obj) {
2798 var width = args[0],
2799 el = this.element;
2801 Dom.setStyle(el, "width", width);
2802 this.cfg.refireEvent("iframe");
2807 * The default event handler fired when the "zIndex" property is changed.
2808 * @method configzIndex
2809 * @param {String} type The CustomEvent type (usually the property name)
2810 * @param {Object[]} args The CustomEvent arguments. For configuration
2811 * handlers, args[0] will equal the newly applied value for the property.
2812 * @param {Object} obj The scope object. For configuration handlers,
2813 * this will usually equal the owner.
2815 configzIndex: function (type, args, obj) {
2817 var zIndex = args[0],
2818 el = this.element;
2820 if (! zIndex) {
2822 zIndex = Dom.getStyle(el, "zIndex");
2824 if (! zIndex || isNaN(zIndex)) {
2826 zIndex = 0;
2832 if (this.iframe) {
2834 if (zIndex <= 0) {
2836 zIndex = 1;
2840 Dom.setStyle(this.iframe, "zIndex", (zIndex - 1));
2843 Dom.setStyle(el, "zIndex", zIndex);
2844 this.cfg.setProperty("zIndex", zIndex, true);
2849 * The default event handler fired when the "xy" property is changed.
2850 * @method configXY
2851 * @param {String} type The CustomEvent type (usually the property name)
2852 * @param {Object[]} args The CustomEvent arguments. For configuration
2853 * handlers, args[0] will equal the newly applied value for the property.
2854 * @param {Object} obj The scope object. For configuration handlers,
2855 * this will usually equal the owner.
2857 configXY: function (type, args, obj) {
2859 var pos = args[0],
2860 x = pos[0],
2861 y = pos[1];
2863 this.cfg.setProperty("x", x);
2864 this.cfg.setProperty("y", y);
2866 this.beforeMoveEvent.fire([x, y]);
2868 x = this.cfg.getProperty("x");
2869 y = this.cfg.getProperty("y");
2872 this.cfg.refireEvent("iframe");
2873 this.moveEvent.fire([x, y]);
2878 * The default event handler fired when the "x" property is changed.
2879 * @method configX
2880 * @param {String} type The CustomEvent type (usually the property name)
2881 * @param {Object[]} args The CustomEvent arguments. For configuration
2882 * handlers, args[0] will equal the newly applied value for the property.
2883 * @param {Object} obj The scope object. For configuration handlers,
2884 * this will usually equal the owner.
2886 configX: function (type, args, obj) {
2888 var x = args[0],
2889 y = this.cfg.getProperty("y");
2891 this.cfg.setProperty("x", x, true);
2892 this.cfg.setProperty("y", y, true);
2894 this.beforeMoveEvent.fire([x, y]);
2896 x = this.cfg.getProperty("x");
2897 y = this.cfg.getProperty("y");
2899 Dom.setX(this.element, x, true);
2901 this.cfg.setProperty("xy", [x, y], true);
2903 this.cfg.refireEvent("iframe");
2904 this.moveEvent.fire([x, y]);
2909 * The default event handler fired when the "y" property is changed.
2910 * @method configY
2911 * @param {String} type The CustomEvent type (usually the property name)
2912 * @param {Object[]} args The CustomEvent arguments. For configuration
2913 * handlers, args[0] will equal the newly applied value for the property.
2914 * @param {Object} obj The scope object. For configuration handlers,
2915 * this will usually equal the owner.
2917 configY: function (type, args, obj) {
2919 var x = this.cfg.getProperty("x"),
2920 y = args[0];
2922 this.cfg.setProperty("x", x, true);
2923 this.cfg.setProperty("y", y, true);
2925 this.beforeMoveEvent.fire([x, y]);
2927 x = this.cfg.getProperty("x");
2928 y = this.cfg.getProperty("y");
2930 Dom.setY(this.element, y, true);
2932 this.cfg.setProperty("xy", [x, y], true);
2934 this.cfg.refireEvent("iframe");
2935 this.moveEvent.fire([x, y]);
2940 * Shows the iframe shim, if it has been enabled.
2941 * @method showIframe
2943 showIframe: function () {
2945 var oIFrame = this.iframe,
2946 oParentNode;
2948 if (oIFrame) {
2950 oParentNode = this.element.parentNode;
2952 if (oParentNode != oIFrame.parentNode) {
2954 oParentNode.appendChild(oIFrame);
2958 oIFrame.style.display = "block";
2965 * Hides the iframe shim, if it has been enabled.
2966 * @method hideIframe
2968 hideIframe: function () {
2970 if (this.iframe) {
2972 this.iframe.style.display = "none";
2979 * Syncronizes the size and position of iframe shim to that of its
2980 * corresponding Overlay instance.
2981 * @method syncIframe
2983 syncIframe: function () {
2985 var oIFrame = this.iframe,
2986 oElement = this.element,
2987 nOffset = Overlay.IFRAME_OFFSET,
2988 nDimensionOffset = (nOffset * 2),
2989 aXY;
2992 if (oIFrame) {
2994 // Size <iframe>
2996 oIFrame.style.width =
2997 (oElement.offsetWidth + nDimensionOffset + "px");
2999 oIFrame.style.height =
3000 (oElement.offsetHeight + nDimensionOffset + "px");
3003 // Position <iframe>
3005 aXY = this.cfg.getProperty("xy");
3007 if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
3009 this.syncPosition();
3011 aXY = this.cfg.getProperty("xy");
3015 Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
3023 * The default event handler fired when the "iframe" property is changed.
3024 * @method configIframe
3025 * @param {String} type The CustomEvent type (usually the property name)
3026 * @param {Object[]} args The CustomEvent arguments. For configuration
3027 * handlers, args[0] will equal the newly applied value for the property.
3028 * @param {Object} obj The scope object. For configuration handlers,
3029 * this will usually equal the owner.
3031 configIframe: function (type, args, obj) {
3033 var bIFrame = args[0];
3035 function createIFrame() {
3037 var oIFrame = this.iframe,
3038 oElement = this.element,
3039 oParent,
3040 aXY;
3043 if (!oIFrame) {
3045 if (!m_oIFrameTemplate) {
3047 m_oIFrameTemplate = document.createElement("iframe");
3049 if (this.isSecure) {
3051 m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
3056 Set the opacity of the <iframe> to 0 so that it
3057 doesn't modify the opacity of any transparent
3058 elements that may be on top of it (like a shadow).
3061 if (YAHOO.env.ua.ie) {
3063 m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
3066 Need to set the "frameBorder" property to 0
3067 supress the default <iframe> border in IE.
3068 Setting the CSS "border" property alone
3069 doesn't supress it.
3072 m_oIFrameTemplate.frameBorder = 0;
3075 else {
3077 m_oIFrameTemplate.style.opacity = "0";
3081 m_oIFrameTemplate.style.position = "absolute";
3082 m_oIFrameTemplate.style.border = "none";
3083 m_oIFrameTemplate.style.margin = "0";
3084 m_oIFrameTemplate.style.padding = "0";
3085 m_oIFrameTemplate.style.display = "none";
3089 oIFrame = m_oIFrameTemplate.cloneNode(false);
3091 oParent = oElement.parentNode;
3093 if (oParent) {
3095 oParent.appendChild(oIFrame);
3097 } else {
3099 document.body.appendChild(oIFrame);
3103 this.iframe = oIFrame;
3109 Show the <iframe> before positioning it since the "setXY"
3110 method of DOM requires the element be in the document
3111 and visible.
3114 this.showIframe();
3118 Syncronize the size and position of the <iframe> to that
3119 of the Overlay.
3122 this.syncIframe();
3125 // Add event listeners to update the <iframe> when necessary
3127 if (!this._hasIframeEventListeners) {
3129 this.showEvent.subscribe(this.showIframe);
3130 this.hideEvent.subscribe(this.hideIframe);
3131 this.changeContentEvent.subscribe(this.syncIframe);
3133 this._hasIframeEventListeners = true;
3140 function onBeforeShow() {
3142 createIFrame.call(this);
3144 this.beforeShowEvent.unsubscribe(onBeforeShow);
3146 this._iframeDeferred = false;
3151 if (bIFrame) { // <iframe> shim is enabled
3153 if (this.cfg.getProperty("visible")) {
3155 createIFrame.call(this);
3158 else {
3160 if (!this._iframeDeferred) {
3162 this.beforeShowEvent.subscribe(onBeforeShow);
3164 this._iframeDeferred = true;
3170 } else { // <iframe> shim is disabled
3172 this.hideIframe();
3174 if (this._hasIframeEventListeners) {
3176 this.showEvent.unsubscribe(this.showIframe);
3177 this.hideEvent.unsubscribe(this.hideIframe);
3178 this.changeContentEvent.unsubscribe(this.syncIframe);
3180 this._hasIframeEventListeners = false;
3190 * The default event handler fired when the "constraintoviewport"
3191 * property is changed.
3192 * @method configConstrainToViewport
3193 * @param {String} type The CustomEvent type (usually the property name)
3194 * @param {Object[]} args The CustomEvent arguments. For configuration
3195 * handlers, args[0] will equal the newly applied value for
3196 * the property.
3197 * @param {Object} obj The scope object. For configuration handlers,
3198 * this will usually equal the owner.
3200 configConstrainToViewport: function (type, args, obj) {
3202 var val = args[0];
3204 if (val) {
3206 if (! Config.alreadySubscribed(this.beforeMoveEvent,
3207 this.enforceConstraints, this)) {
3209 this.beforeMoveEvent.subscribe(this.enforceConstraints,
3210 this, true);
3214 } else {
3216 this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
3223 * The default event handler fired when the "context" property
3224 * is changed.
3225 * @method configContext
3226 * @param {String} type The CustomEvent type (usually the property name)
3227 * @param {Object[]} args The CustomEvent arguments. For configuration
3228 * handlers, args[0] will equal the newly applied value for the property.
3229 * @param {Object} obj The scope object. For configuration handlers,
3230 * this will usually equal the owner.
3232 configContext: function (type, args, obj) {
3234 var contextArgs = args[0],
3235 contextEl,
3236 elementMagnetCorner,
3237 contextMagnetCorner;
3239 if (contextArgs) {
3241 contextEl = contextArgs[0];
3242 elementMagnetCorner = contextArgs[1];
3243 contextMagnetCorner = contextArgs[2];
3245 if (contextEl) {
3247 if (typeof contextEl == "string") {
3249 this.cfg.setProperty("context",
3250 [document.getElementById(contextEl),
3251 elementMagnetCorner, contextMagnetCorner],
3252 true);
3256 if (elementMagnetCorner && contextMagnetCorner) {
3258 this.align(elementMagnetCorner, contextMagnetCorner);
3269 // END BUILT-IN PROPERTY EVENT HANDLERS //
3272 * Aligns the Overlay to its context element using the specified corner
3273 * points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT,
3274 * and BOTTOM_RIGHT.
3275 * @method align
3276 * @param {String} elementAlign The String representing the corner of
3277 * the Overlay that should be aligned to the context element
3278 * @param {String} contextAlign The corner of the context element
3279 * that the elementAlign corner should stick to.
3281 align: function (elementAlign, contextAlign) {
3283 var contextArgs = this.cfg.getProperty("context"),
3284 me = this,
3285 context,
3286 element,
3287 contextRegion;
3290 function doAlign(v, h) {
3292 switch (elementAlign) {
3294 case Overlay.TOP_LEFT:
3296 me.moveTo(h, v);
3298 break;
3300 case Overlay.TOP_RIGHT:
3302 me.moveTo((h - element.offsetWidth), v);
3304 break;
3306 case Overlay.BOTTOM_LEFT:
3308 me.moveTo(h, (v - element.offsetHeight));
3310 break;
3312 case Overlay.BOTTOM_RIGHT:
3314 me.moveTo((h - element.offsetWidth),
3315 (v - element.offsetHeight));
3317 break;
3324 if (contextArgs) {
3326 context = contextArgs[0];
3327 element = this.element;
3328 me = this;
3330 if (! elementAlign) {
3332 elementAlign = contextArgs[1];
3336 if (! contextAlign) {
3338 contextAlign = contextArgs[2];
3342 if (element && context) {
3344 contextRegion = Dom.getRegion(context);
3346 switch (contextAlign) {
3348 case Overlay.TOP_LEFT:
3350 doAlign(contextRegion.top, contextRegion.left);
3352 break;
3354 case Overlay.TOP_RIGHT:
3356 doAlign(contextRegion.top, contextRegion.right);
3358 break;
3360 case Overlay.BOTTOM_LEFT:
3362 doAlign(contextRegion.bottom, contextRegion.left);
3364 break;
3366 case Overlay.BOTTOM_RIGHT:
3368 doAlign(contextRegion.bottom, contextRegion.right);
3370 break;
3381 * The default event handler executed when the moveEvent is fired, if the
3382 * "constraintoviewport" is set to true.
3383 * @method enforceConstraints
3384 * @param {String} type The CustomEvent type (usually the property name)
3385 * @param {Object[]} args The CustomEvent arguments. For configuration
3386 * handlers, args[0] will equal the newly applied value for the property.
3387 * @param {Object} obj The scope object. For configuration handlers,
3388 * this will usually equal the owner.
3390 enforceConstraints: function (type, args, obj) {
3392 var pos = args[0],
3393 x = pos[0],
3394 y = pos[1],
3395 offsetHeight = this.element.offsetHeight,
3396 offsetWidth = this.element.offsetWidth,
3397 viewPortWidth = Dom.getViewportWidth(),
3398 viewPortHeight = Dom.getViewportHeight(),
3399 scrollX = Dom.getDocumentScrollLeft(),
3400 scrollY = Dom.getDocumentScrollTop(),
3401 topConstraint = scrollY + 10,
3402 leftConstraint = scrollX + 10,
3403 bottomConstraint = scrollY + viewPortHeight - offsetHeight - 10,
3404 rightConstraint = scrollX + viewPortWidth - offsetWidth - 10;
3407 if (x < leftConstraint) {
3409 x = leftConstraint;
3411 } else if (x > rightConstraint) {
3413 x = rightConstraint;
3417 if (y < topConstraint) {
3419 y = topConstraint;
3421 } else if (y > bottomConstraint) {
3423 y = bottomConstraint;
3427 this.cfg.setProperty("x", x, true);
3428 this.cfg.setProperty("y", y, true);
3429 this.cfg.setProperty("xy", [x, y], true);
3434 * Centers the container in the viewport.
3435 * @method center
3437 center: function () {
3439 var scrollX = Dom.getDocumentScrollLeft(),
3440 scrollY = Dom.getDocumentScrollTop(),
3442 viewPortWidth = Dom.getClientWidth(),
3443 viewPortHeight = Dom.getClientHeight(),
3444 elementWidth = this.element.offsetWidth,
3445 elementHeight = this.element.offsetHeight,
3446 x = (viewPortWidth / 2) - (elementWidth / 2) + scrollX,
3447 y = (viewPortHeight / 2) - (elementHeight / 2) + scrollY;
3449 this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
3451 this.cfg.refireEvent("iframe");
3456 * Synchronizes the Panel's "xy", "x", and "y" properties with the
3457 * Panel's position in the DOM. This is primarily used to update
3458 * position information during drag & drop.
3459 * @method syncPosition
3461 syncPosition: function () {
3463 var pos = Dom.getXY(this.element);
3465 this.cfg.setProperty("x", pos[0], true);
3466 this.cfg.setProperty("y", pos[1], true);
3467 this.cfg.setProperty("xy", pos, true);
3472 * Event handler fired when the resize monitor element is resized.
3473 * @method onDomResize
3474 * @param {DOMEvent} e The resize DOM event
3475 * @param {Object} obj The scope object
3477 onDomResize: function (e, obj) {
3479 var me = this;
3481 Overlay.superclass.onDomResize.call(this, e, obj);
3483 setTimeout(function () {
3484 me.syncPosition();
3485 me.cfg.refireEvent("iframe");
3486 me.cfg.refireEvent("context");
3487 }, 0);
3492 * Places the Overlay on top of all other instances of
3493 * YAHOO.widget.Overlay.
3494 * @method bringToTop
3496 bringToTop: function() {
3498 var aOverlays = [],
3499 oElement = this.element;
3501 function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
3503 var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
3505 sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
3507 nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ?
3508 0 : parseInt(sZIndex1, 10),
3510 nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ?
3511 0 : parseInt(sZIndex2, 10);
3513 if (nZIndex1 > nZIndex2) {
3515 return -1;
3517 } else if (nZIndex1 < nZIndex2) {
3519 return 1;
3521 } else {
3523 return 0;
3529 function isOverlayElement(p_oElement) {
3531 var oOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
3532 Panel = YAHOO.widget.Panel;
3534 if (oOverlay && !Dom.isAncestor(oElement, oOverlay)) {
3536 if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
3538 aOverlays[aOverlays.length] = p_oElement.parentNode;
3541 else {
3543 aOverlays[aOverlays.length] = p_oElement;
3551 Dom.getElementsBy(isOverlayElement, "DIV", document.body);
3553 aOverlays.sort(compareZIndexDesc);
3555 var oTopOverlay = aOverlays[0],
3556 nTopZIndex;
3558 if (oTopOverlay) {
3560 nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
3562 if (!isNaN(nTopZIndex) && oTopOverlay != oElement) {
3564 this.cfg.setProperty("zindex",
3565 (parseInt(nTopZIndex, 10) + 2));
3574 * Removes the Overlay element from the DOM and sets all child
3575 * elements to null.
3576 * @method destroy
3578 destroy: function () {
3580 if (this.iframe) {
3582 this.iframe.parentNode.removeChild(this.iframe);
3586 this.iframe = null;
3588 Overlay.windowResizeEvent.unsubscribe(
3589 this.doCenterOnDOMEvent, this);
3591 Overlay.windowScrollEvent.unsubscribe(
3592 this.doCenterOnDOMEvent, this);
3594 Overlay.superclass.destroy.call(this);
3598 * Returns a String representation of the object.
3599 * @method toString
3600 * @return {String} The string representation of the Overlay.
3602 toString: function () {
3604 return "Overlay " + this.id;
3610 }());
3611 (function () {
3614 * OverlayManager is used for maintaining the focus status of
3615 * multiple Overlays.
3616 * @namespace YAHOO.widget
3617 * @namespace YAHOO.widget
3618 * @class OverlayManager
3619 * @constructor
3620 * @param {Array} overlays Optional. A collection of Overlays to register
3621 * with the manager.
3622 * @param {Object} userConfig The object literal representing the user
3623 * configuration of the OverlayManager
3625 YAHOO.widget.OverlayManager = function (userConfig) {
3627 this.init(userConfig);
3632 var Overlay = YAHOO.widget.Overlay,
3633 Event = YAHOO.util.Event,
3634 Dom = YAHOO.util.Dom,
3635 Config = YAHOO.util.Config,
3636 CustomEvent = YAHOO.util.CustomEvent,
3637 OverlayManager = YAHOO.widget.OverlayManager;
3641 * The CSS class representing a focused Overlay
3642 * @property OverlayManager.CSS_FOCUSED
3643 * @static
3644 * @final
3645 * @type String
3647 OverlayManager.CSS_FOCUSED = "focused";
3649 OverlayManager.prototype = {
3652 * The class's constructor function
3653 * @property contructor
3654 * @type Function
3656 constructor: OverlayManager,
3659 * The array of Overlays that are currently registered
3660 * @property overlays
3661 * @type YAHOO.widget.Overlay[]
3663 overlays: null,
3666 * Initializes the default configuration of the OverlayManager
3667 * @method initDefaultConfig
3669 initDefaultConfig: function () {
3672 * The collection of registered Overlays in use by
3673 * the OverlayManager
3674 * @config overlays
3675 * @type YAHOO.widget.Overlay[]
3676 * @default null
3678 this.cfg.addProperty("overlays", { suppressEvent: true } );
3681 * The default DOM event that should be used to focus an Overlay
3682 * @config focusevent
3683 * @type String
3684 * @default "mousedown"
3686 this.cfg.addProperty("focusevent", { value: "mousedown" } );
3691 * Initializes the OverlayManager
3692 * @method init
3693 * @param {Overlay[]} overlays Optional. A collection of Overlays to
3694 * register with the manager.
3695 * @param {Object} userConfig The object literal representing the user
3696 * configuration of the OverlayManager
3698 init: function (userConfig) {
3701 * The OverlayManager's Config object used for monitoring
3702 * configuration properties.
3703 * @property cfg
3704 * @type Config
3706 this.cfg = new Config(this);
3708 this.initDefaultConfig();
3710 if (userConfig) {
3711 this.cfg.applyConfig(userConfig, true);
3713 this.cfg.fireQueue();
3716 * The currently activated Overlay
3717 * @property activeOverlay
3718 * @private
3719 * @type YAHOO.widget.Overlay
3721 var activeOverlay = null;
3724 * Returns the currently focused Overlay
3725 * @method getActive
3726 * @return {Overlay} The currently focused Overlay
3728 this.getActive = function () {
3729 return activeOverlay;
3733 * Focuses the specified Overlay
3734 * @method focus
3735 * @param {Overlay} overlay The Overlay to focus
3736 * @param {String} overlay The id of the Overlay to focus
3738 this.focus = function (overlay) {
3740 var o = this.find(overlay);
3742 if (o) {
3744 if (activeOverlay != o) {
3746 if (activeOverlay) {
3748 activeOverlay.blur();
3752 this.bringToTop(o);
3754 activeOverlay = o;
3756 Dom.addClass(activeOverlay.element,
3757 OverlayManager.CSS_FOCUSED);
3759 o.focusEvent.fire();
3768 * Removes the specified Overlay from the manager
3769 * @method remove
3770 * @param {Overlay} overlay The Overlay to remove
3771 * @param {String} overlay The id of the Overlay to remove
3773 this.remove = function (overlay) {
3775 var o = this.find(overlay),
3776 originalZ;
3778 if (o) {
3780 if (activeOverlay == o) {
3782 activeOverlay = null;
3786 originalZ = Dom.getStyle(o.element, "zIndex");
3788 o.cfg.setProperty("zIndex", -1000, true);
3790 this.overlays.sort(this.compareZIndexDesc);
3792 this.overlays =
3793 this.overlays.slice(0, (this.overlays.length - 1));
3795 o.hideEvent.unsubscribe(o.blur);
3796 o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
3798 if (o.element) {
3800 Event.removeListener(o.element,
3801 this.cfg.getProperty("focusevent"),
3802 this._onOverlayElementFocus);
3806 o.cfg.setProperty("zIndex", originalZ, true);
3807 o.cfg.setProperty("manager", null);
3809 o.focusEvent.unsubscribeAll();
3810 o.blurEvent.unsubscribeAll();
3812 o.focusEvent = null;
3813 o.blurEvent = null;
3815 o.focus = null;
3816 o.blur = null;
3822 * Removes focus from all registered Overlays in the manager
3823 * @method blurAll
3825 this.blurAll = function () {
3827 var nOverlays = this.overlays.length,
3830 if (nOverlays > 0) {
3832 i = nOverlays - 1;
3834 do {
3836 this.overlays[i].blur();
3839 while(i--);
3846 this._onOverlayBlur = function (p_sType, p_aArgs) {
3848 activeOverlay = null;
3853 var overlays = this.cfg.getProperty("overlays");
3855 if (! this.overlays) {
3856 this.overlays = [];
3859 if (overlays) {
3860 this.register(overlays);
3861 this.overlays.sort(this.compareZIndexDesc);
3867 * @method _onOverlayElementFocus
3868 * @description Event handler for the DOM event that is used to focus
3869 * the Overlay instance as specified by the "focusevent"
3870 * configuration property.
3871 * @private
3872 * @param {Event} p_oEvent Object representing the DOM event
3873 * object passed back by the event utility (Event).
3875 _onOverlayElementFocus: function (p_oEvent) {
3877 var oTarget = Event.getTarget(p_oEvent),
3878 oClose = this.close;
3881 if (oClose && (oTarget == oClose ||
3882 Dom.isAncestor(oClose, oTarget))) {
3884 this.blur();
3887 else {
3889 this.focus();
3897 * @method _onOverlayDestroy
3898 * @description "destroy" event handler for the Overlay.
3899 * @private
3900 * @param {String} p_sType String representing the name of the event
3901 * that was fired.
3902 * @param {Array} p_aArgs Array of arguments sent when the event
3903 * was fired.
3904 * @param {Overlay} p_oOverlay Object representing the menu that
3905 * fired the event.
3907 _onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
3909 this.remove(p_oOverlay);
3914 * Registers an Overlay or an array of Overlays with the manager. Upon
3915 * registration, the Overlay receives functions for focus and blur,
3916 * along with CustomEvents for each.
3917 * @method register
3918 * @param {Overlay} overlay An Overlay to register with the manager.
3919 * @param {Overlay[]} overlay An array of Overlays to register with
3920 * the manager.
3921 * @return {Boolean} True if any Overlays are registered.
3923 register: function (overlay) {
3925 var mgr = this,
3926 zIndex,
3927 regcount,
3929 nOverlays;
3931 if (overlay instanceof Overlay) {
3933 overlay.cfg.addProperty("manager", { value: this } );
3935 overlay.focusEvent = overlay.createEvent("focus");
3936 overlay.focusEvent.signature = CustomEvent.LIST;
3938 overlay.blurEvent = overlay.createEvent("blur");
3939 overlay.blurEvent.signature = CustomEvent.LIST;
3941 overlay.focus = function () {
3942 mgr.focus(this);
3945 overlay.blur = function () {
3947 if (mgr.getActive() == this) {
3949 Dom.removeClass(this.element,
3950 OverlayManager.CSS_FOCUSED);
3952 this.blurEvent.fire();
3958 overlay.blurEvent.subscribe(mgr._onOverlayBlur);
3960 overlay.hideEvent.subscribe(overlay.blur);
3962 overlay.destroyEvent.subscribe(this._onOverlayDestroy,
3963 overlay, this);
3965 Event.on(overlay.element, this.cfg.getProperty("focusevent"),
3966 this._onOverlayElementFocus, null, overlay);
3968 zIndex = Dom.getStyle(overlay.element, "zIndex");
3970 if (!isNaN(zIndex)) {
3972 overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
3974 } else {
3976 overlay.cfg.setProperty("zIndex", 0);
3981 this.overlays.push(overlay);
3983 this.bringToTop(overlay);
3985 return true;
3987 } else if (overlay instanceof Array) {
3989 regcount = 0;
3990 nOverlays = overlay.length;
3992 for (i = 0; i < nOverlays; i++) {
3994 if (this.register(overlay[i])) {
3996 regcount++;
4001 if (regcount > 0) {
4003 return true;
4007 } else {
4009 return false;
4016 * Places the specified Overlay instance on top of all other
4017 * Overlay instances.
4018 * @method bringToTop
4019 * @param {YAHOO.widget.Overlay} p_oOverlay Object representing an
4020 * Overlay instance.
4021 * @param {String} p_oOverlay String representing the id of an
4022 * Overlay instance.
4024 bringToTop: function (p_oOverlay) {
4026 var oOverlay = this.find(p_oOverlay),
4027 nTopZIndex,
4028 oTopOverlay,
4029 aOverlays;
4031 if (oOverlay) {
4033 aOverlays = this.overlays;
4035 aOverlays.sort(this.compareZIndexDesc);
4037 oTopOverlay = aOverlays[0];
4039 if (oTopOverlay) {
4041 nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
4043 if (!isNaN(nTopZIndex) && oTopOverlay != oOverlay) {
4045 oOverlay.cfg.setProperty("zIndex",
4046 (parseInt(nTopZIndex, 10) + 2));
4050 aOverlays.sort(this.compareZIndexDesc);
4059 * Attempts to locate an Overlay by instance or ID.
4060 * @method find
4061 * @param {Overlay} overlay An Overlay to locate within the manager
4062 * @param {String} overlay An Overlay id to locate within the manager
4063 * @return {Overlay} The requested Overlay, if found, or null if it
4064 * cannot be located.
4066 find: function (overlay) {
4068 var aOverlays = this.overlays,
4069 nOverlays = aOverlays.length,
4072 if (nOverlays > 0) {
4074 i = nOverlays - 1;
4076 if (overlay instanceof Overlay) {
4078 do {
4080 if (aOverlays[i] == overlay) {
4082 return aOverlays[i];
4087 while(i--);
4089 } else if (typeof overlay == "string") {
4091 do {
4093 if (aOverlays[i].id == overlay) {
4095 return aOverlays[i];
4100 while(i--);
4104 return null;
4111 * Used for sorting the manager's Overlays by z-index.
4112 * @method compareZIndexDesc
4113 * @private
4114 * @return {Number} 0, 1, or -1, depending on where the Overlay should
4115 * fall in the stacking order.
4117 compareZIndexDesc: function (o1, o2) {
4119 var zIndex1 = o1.cfg.getProperty("zIndex"),
4120 zIndex2 = o2.cfg.getProperty("zIndex");
4122 if (zIndex1 > zIndex2) {
4123 return -1;
4124 } else if (zIndex1 < zIndex2) {
4125 return 1;
4126 } else {
4127 return 0;
4132 * Shows all Overlays in the manager.
4133 * @method showAll
4135 showAll: function () {
4137 var aOverlays = this.overlays,
4138 nOverlays = aOverlays.length,
4141 if (nOverlays > 0) {
4143 i = nOverlays - 1;
4145 do {
4147 aOverlays[i].show();
4150 while(i--);
4157 * Hides all Overlays in the manager.
4158 * @method hideAll
4160 hideAll: function () {
4162 var aOverlays = this.overlays,
4163 nOverlays = aOverlays.length,
4166 if (nOverlays > 0) {
4168 i = nOverlays - 1;
4170 do {
4172 aOverlays[i].hide();
4175 while(i--);
4182 * Returns a string representation of the object.
4183 * @method toString
4184 * @return {String} The string representation of the OverlayManager
4186 toString: function () {
4187 return "OverlayManager";
4192 }());
4193 (function () {
4196 * ContainerEffect encapsulates animation transitions that are executed when
4197 * an Overlay is shown or hidden.
4198 * @namespace YAHOO.widget
4199 * @class ContainerEffect
4200 * @constructor
4201 * @param {YAHOO.widget.Overlay} overlay The Overlay that the animation
4202 * should be associated with
4203 * @param {Object} attrIn The object literal representing the animation
4204 * arguments to be used for the animate-in transition. The arguments for
4205 * this literal are: attributes(object, see YAHOO.util.Anim for description),
4206 * duration(Number), and method(i.e. Easing.easeIn).
4207 * @param {Object} attrOut The object literal representing the animation
4208 * arguments to be used for the animate-out transition. The arguments for
4209 * this literal are: attributes(object, see YAHOO.util.Anim for description),
4210 * duration(Number), and method(i.e. Easing.easeIn).
4211 * @param {HTMLElement} targetElement Optional. The target element that
4212 * should be animated during the transition. Defaults to overlay.element.
4213 * @param {class} Optional. The animation class to instantiate. Defaults to
4214 * YAHOO.util.Anim. Other options include YAHOO.util.Motion.
4216 YAHOO.widget.ContainerEffect =
4218 function (overlay, attrIn, attrOut, targetElement, animClass) {
4220 if (!animClass) {
4221 animClass = YAHOO.util.Anim;
4225 * The overlay to animate
4226 * @property overlay
4227 * @type YAHOO.widget.Overlay
4229 this.overlay = overlay;
4232 * The animation attributes to use when transitioning into view
4233 * @property attrIn
4234 * @type Object
4236 this.attrIn = attrIn;
4239 * The animation attributes to use when transitioning out of view
4240 * @property attrOut
4241 * @type Object
4243 this.attrOut = attrOut;
4246 * The target element to be animated
4247 * @property targetElement
4248 * @type HTMLElement
4250 this.targetElement = targetElement || overlay.element;
4253 * The animation class to use for animating the overlay
4254 * @property animClass
4255 * @type class
4257 this.animClass = animClass;
4262 var Dom = YAHOO.util.Dom,
4263 CustomEvent = YAHOO.util.CustomEvent,
4264 Easing = YAHOO.util.Easing,
4265 ContainerEffect = YAHOO.widget.ContainerEffect;
4269 * A pre-configured ContainerEffect instance that can be used for fading
4270 * an overlay in and out.
4271 * @method FADE
4272 * @static
4273 * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
4274 * @param {Number} dur The duration of the animation
4275 * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
4277 ContainerEffect.FADE = function (overlay, dur) {
4279 var fade = new ContainerEffect(overlay,
4281 { attributes: { opacity: { from: 0, to: 1 } },
4282 duration: dur,
4283 method: Easing.easeIn },
4285 { attributes: { opacity: { to: 0 } },
4286 duration: dur,
4287 method: Easing.easeOut },
4289 overlay.element);
4292 fade.handleStartAnimateIn = function (type,args,obj) {
4293 Dom.addClass(obj.overlay.element, "hide-select");
4295 if (! obj.overlay.underlay) {
4296 obj.overlay.cfg.refireEvent("underlay");
4299 if (obj.overlay.underlay) {
4301 obj.initialUnderlayOpacity =
4302 Dom.getStyle(obj.overlay.underlay, "opacity");
4304 obj.overlay.underlay.style.filter = null;
4308 Dom.setStyle(obj.overlay.element, "visibility", "visible");
4309 Dom.setStyle(obj.overlay.element, "opacity", 0);
4313 fade.handleCompleteAnimateIn = function (type,args,obj) {
4314 Dom.removeClass(obj.overlay.element, "hide-select");
4316 if (obj.overlay.element.style.filter) {
4317 obj.overlay.element.style.filter = null;
4320 if (obj.overlay.underlay) {
4321 Dom.setStyle(obj.overlay.underlay, "opacity",
4322 obj.initialUnderlayOpacity);
4325 obj.overlay.cfg.refireEvent("iframe");
4326 obj.animateInCompleteEvent.fire();
4330 fade.handleStartAnimateOut = function (type, args, obj) {
4331 Dom.addClass(obj.overlay.element, "hide-select");
4333 if (obj.overlay.underlay) {
4334 obj.overlay.underlay.style.filter = null;
4339 fade.handleCompleteAnimateOut = function (type, args, obj) {
4340 Dom.removeClass(obj.overlay.element, "hide-select");
4341 if (obj.overlay.element.style.filter) {
4342 obj.overlay.element.style.filter = null;
4344 Dom.setStyle(obj.overlay.element, "visibility", "hidden");
4345 Dom.setStyle(obj.overlay.element, "opacity", 1);
4347 obj.overlay.cfg.refireEvent("iframe");
4349 obj.animateOutCompleteEvent.fire();
4352 fade.init();
4353 return fade;
4358 * A pre-configured ContainerEffect instance that can be used for sliding an
4359 * overlay in and out.
4360 * @method SLIDE
4361 * @static
4362 * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
4363 * @param {Number} dur The duration of the animation
4364 * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
4366 ContainerEffect.SLIDE = function (overlay, dur) {
4368 var x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
4370 y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
4372 clientWidth = Dom.getClientWidth(),
4374 offsetWidth = overlay.element.offsetWidth,
4376 slide = new ContainerEffect(overlay,
4378 { attributes: { points: { to: [x, y] } },
4379 duration: dur,
4380 method: Easing.easeIn },
4382 { attributes: { points: { to: [(clientWidth + 25), y] } },
4383 duration: dur,
4384 method: Easing.easeOut },
4386 overlay.element, YAHOO.util.Motion);
4389 slide.handleStartAnimateIn = function (type,args,obj) {
4390 obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
4391 obj.overlay.element.style.top = y + "px";
4394 slide.handleTweenAnimateIn = function (type, args, obj) {
4396 var pos = Dom.getXY(obj.overlay.element),
4397 currentX = pos[0],
4398 currentY = pos[1];
4400 if (Dom.getStyle(obj.overlay.element, "visibility") ==
4401 "hidden" && currentX < x) {
4403 Dom.setStyle(obj.overlay.element, "visibility", "visible");
4407 obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
4408 obj.overlay.cfg.refireEvent("iframe");
4411 slide.handleCompleteAnimateIn = function (type, args, obj) {
4412 obj.overlay.cfg.setProperty("xy", [x, y], true);
4413 obj.startX = x;
4414 obj.startY = y;
4415 obj.overlay.cfg.refireEvent("iframe");
4416 obj.animateInCompleteEvent.fire();
4419 slide.handleStartAnimateOut = function (type, args, obj) {
4421 var vw = Dom.getViewportWidth(),
4422 pos = Dom.getXY(obj.overlay.element),
4423 yso = pos[1],
4424 currentTo = obj.animOut.attributes.points.to;
4426 obj.animOut.attributes.points.to = [(vw + 25), yso];
4430 slide.handleTweenAnimateOut = function (type, args, obj) {
4432 var pos = Dom.getXY(obj.overlay.element),
4433 xto = pos[0],
4434 yto = pos[1];
4436 obj.overlay.cfg.setProperty("xy", [xto, yto], true);
4437 obj.overlay.cfg.refireEvent("iframe");
4440 slide.handleCompleteAnimateOut = function (type, args, obj) {
4441 Dom.setStyle(obj.overlay.element, "visibility", "hidden");
4443 obj.overlay.cfg.setProperty("xy", [x, y]);
4444 obj.animateOutCompleteEvent.fire();
4447 slide.init();
4448 return slide;
4451 ContainerEffect.prototype = {
4454 * Initializes the animation classes and events.
4455 * @method init
4457 init: function () {
4459 this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
4460 this.beforeAnimateInEvent.signature = CustomEvent.LIST;
4462 this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
4463 this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
4465 this.animateInCompleteEvent = this.createEvent("animateInComplete");
4466 this.animateInCompleteEvent.signature = CustomEvent.LIST;
4468 this.animateOutCompleteEvent =
4469 this.createEvent("animateOutComplete");
4470 this.animateOutCompleteEvent.signature = CustomEvent.LIST;
4472 this.animIn = new this.animClass(this.targetElement,
4473 this.attrIn.attributes, this.attrIn.duration,
4474 this.attrIn.method);
4476 this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
4477 this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
4479 this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn,
4480 this);
4482 this.animOut = new this.animClass(this.targetElement,
4483 this.attrOut.attributes, this.attrOut.duration,
4484 this.attrOut.method);
4486 this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
4487 this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
4488 this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut,
4489 this);
4494 * Triggers the in-animation.
4495 * @method animateIn
4497 animateIn: function () {
4498 this.beforeAnimateInEvent.fire();
4499 this.animIn.animate();
4503 * Triggers the out-animation.
4504 * @method animateOut
4506 animateOut: function () {
4507 this.beforeAnimateOutEvent.fire();
4508 this.animOut.animate();
4512 * The default onStart handler for the in-animation.
4513 * @method handleStartAnimateIn
4514 * @param {String} type The CustomEvent type
4515 * @param {Object[]} args The CustomEvent arguments
4516 * @param {Object} obj The scope object
4518 handleStartAnimateIn: function (type, args, obj) { },
4521 * The default onTween handler for the in-animation.
4522 * @method handleTweenAnimateIn
4523 * @param {String} type The CustomEvent type
4524 * @param {Object[]} args The CustomEvent arguments
4525 * @param {Object} obj The scope object
4527 handleTweenAnimateIn: function (type, args, obj) { },
4530 * The default onComplete handler for the in-animation.
4531 * @method handleCompleteAnimateIn
4532 * @param {String} type The CustomEvent type
4533 * @param {Object[]} args The CustomEvent arguments
4534 * @param {Object} obj The scope object
4536 handleCompleteAnimateIn: function (type, args, obj) { },
4539 * The default onStart handler for the out-animation.
4540 * @method handleStartAnimateOut
4541 * @param {String} type The CustomEvent type
4542 * @param {Object[]} args The CustomEvent arguments
4543 * @param {Object} obj The scope object
4545 handleStartAnimateOut: function (type, args, obj) { },
4548 * The default onTween handler for the out-animation.
4549 * @method handleTweenAnimateOut
4550 * @param {String} type The CustomEvent type
4551 * @param {Object[]} args The CustomEvent arguments
4552 * @param {Object} obj The scope object
4554 handleTweenAnimateOut: function (type, args, obj) { },
4557 * The default onComplete handler for the out-animation.
4558 * @method handleCompleteAnimateOut
4559 * @param {String} type The CustomEvent type
4560 * @param {Object[]} args The CustomEvent arguments
4561 * @param {Object} obj The scope object
4563 handleCompleteAnimateOut: function (type, args, obj) { },
4566 * Returns a string representation of the object.
4567 * @method toString
4568 * @return {String} The string representation of the ContainerEffect
4570 toString: function () {
4571 var output = "ContainerEffect";
4572 if (this.overlay) {
4573 output += " [" + this.overlay.toString() + "]";
4575 return output;
4580 YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
4582 })();
4583 YAHOO.register("container_core", YAHOO.widget.Module, {version: "2.3.0", build: "442"});