2
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3
Code licensed under the BSD License:
4
http://developer.yahoo.net/yui/license.txt
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
18
* @param {Object} owner The owner Object to which this Config Object belongs
20
YAHOO.util.Config = function (owner) {
30
var Lang = YAHOO.lang,
31
CustomEvent = YAHOO.util.CustomEvent,
32
Config = YAHOO.util.Config;
36
* Constant representing the CustomEvent type for the config changed event.
37
* @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
42
Config.CONFIG_CHANGED_EVENT = "configChanged";
45
* Constant representing the boolean type string
46
* @property YAHOO.util.Config.BOOLEAN_TYPE
51
Config.BOOLEAN_TYPE = "boolean";
56
* Object reference to the owner of this Config Object
63
* Boolean flag that specifies whether a queue is currently
65
* @property queueInProgress
68
queueInProgress: false,
71
* Maintains the local collection of configuration property objects and
72
* their specified values
80
* Maintains the local collection of configuration property objects as
81
* they were initially applied.
82
* This object is used when resetting a property.
83
* @property initialConfig
90
* Maintains the local, normalized CustomEvent queue
91
* @property eventQueue
98
* Custom Event, notifying subscribers when Config properties are set
99
* (setProperty is called without the silent flag
100
* @event configChangedEvent
102
configChangedEvent: null,
105
* Initializes the configuration Object and all of its local members.
107
* @param {Object} owner The owner Object to which this Config
110
init: function (owner) {
114
this.configChangedEvent =
115
this.createEvent(Config.CONFIG_CHANGED_EVENT);
117
this.configChangedEvent.signature = CustomEvent.LIST;
118
this.queueInProgress = false;
120
this.initialConfig = {};
121
this.eventQueue = [];
126
* Validates that the value passed in is a Boolean.
127
* @method checkBoolean
128
* @param {Object} val The value to validate
129
* @return {Boolean} true, if the value is valid
131
checkBoolean: function (val) {
132
return (typeof val == Config.BOOLEAN_TYPE);
136
* Validates that the value passed in is a number.
137
* @method checkNumber
138
* @param {Object} val The value to validate
139
* @return {Boolean} true, if the value is valid
141
checkNumber: function (val) {
142
return (!isNaN(val));
146
* Fires a configuration property event using the specified value.
149
* @param {String} key The configuration property's name
150
* @param {value} Object The value of the correct type for the property
152
fireEvent: function ( key, value ) {
153
var property = this.config[key];
155
if (property && property.event) {
156
property.event.fire(value);
161
* Adds a property to the Config Object's private config hash.
162
* @method addProperty
163
* @param {String} key The configuration property's name
164
* @param {Object} propertyObject The Object containing all of this
165
* property's arguments
167
addProperty: function ( key, propertyObject ) {
168
key = key.toLowerCase();
170
this.config[key] = propertyObject;
172
propertyObject.event = this.createEvent(key, { scope: this.owner });
173
propertyObject.event.signature = CustomEvent.LIST;
176
propertyObject.key = key;
178
if (propertyObject.handler) {
179
propertyObject.event.subscribe(propertyObject.handler,
183
this.setProperty(key, propertyObject.value, true);
185
if (! propertyObject.suppressEvent) {
186
this.queueProperty(key, propertyObject.value);
192
* Returns a key-value configuration map of the values currently set in
195
* @return {Object} The current config, represented in a key-value map
197
getConfig: function () {
200
currCfg = this.config,
204
for (prop in currCfg) {
205
if (Lang.hasOwnProperty(currCfg, prop)) {
206
property = currCfg[prop];
207
if (property && property.event) {
208
cfg[prop] = property.value;
217
* Returns the value of specified property.
218
* @method getProperty
219
* @param {String} key The name of the property
220
* @return {Object} The value of the specified property
222
getProperty: function (key) {
223
var property = this.config[key.toLowerCase()];
224
if (property && property.event) {
225
return property.value;
232
* Resets the specified property's value to its initial value.
233
* @method resetProperty
234
* @param {String} key The name of the property
235
* @return {Boolean} True is the property was reset, false if not
237
resetProperty: function (key) {
239
key = key.toLowerCase();
241
var property = this.config[key];
243
if (property && property.event) {
245
if (this.initialConfig[key] &&
246
!Lang.isUndefined(this.initialConfig[key])) {
248
this.setProperty(key, this.initialConfig[key]);
262
* Sets the value of a property. If the silent property is passed as
263
* true, the property's event will not be fired.
264
* @method setProperty
265
* @param {String} key The name of the property
266
* @param {String} value The value to set the property to
267
* @param {Boolean} silent Whether the value should be set silently,
268
* without firing the property event.
269
* @return {Boolean} True, if the set was successful, false if it failed.
271
setProperty: function (key, value, silent) {
275
key = key.toLowerCase();
277
if (this.queueInProgress && ! silent) {
278
// Currently running through a queue...
279
this.queueProperty(key,value);
283
property = this.config[key];
284
if (property && property.event) {
285
if (property.validator && !property.validator(value)) {
288
property.value = value;
290
this.fireEvent(key, value);
291
this.configChangedEvent.fire([key, value]);
302
* Sets the value of a property and queues its event to execute. If the
303
* event is already scheduled to execute, it is
304
* moved from its current position to the end of the queue.
305
* @method queueProperty
306
* @param {String} key The name of the property
307
* @param {String} value The value to set the property to
308
* @return {Boolean} true, if the set was successful, false if
311
queueProperty: function (key, value) {
313
key = key.toLowerCase();
315
var property = this.config[key],
316
foundDuplicate = false,
331
if (property && property.event) {
333
if (!Lang.isUndefined(value) && property.validator &&
334
!property.validator(value)) { // validator
338
if (!Lang.isUndefined(value)) {
339
property.value = value;
341
value = property.value;
344
foundDuplicate = false;
345
iLen = this.eventQueue.length;
347
for (i = 0; i < iLen; i++) {
348
queueItem = this.eventQueue[i];
351
queueItemKey = queueItem[0];
352
queueItemValue = queueItem[1];
354
if (queueItemKey == key) {
357
found a dupe... push to end of queue, null
358
current item, and break
361
this.eventQueue[i] = null;
363
this.eventQueue.push(
364
[key, (!Lang.isUndefined(value) ?
365
value : queueItemValue)]);
367
foundDuplicate = true;
373
// this is a refire, or a new property in the queue
375
if (! foundDuplicate && !Lang.isUndefined(value)) {
376
this.eventQueue.push([key, value]);
380
if (property.supercedes) {
382
sLen = property.supercedes.length;
384
for (s = 0; s < sLen; s++) {
386
supercedesCheck = property.supercedes[s];
387
qLen = this.eventQueue.length;
389
for (q = 0; q < qLen; q++) {
390
queueItemCheck = this.eventQueue[q];
392
if (queueItemCheck) {
393
queueItemCheckKey = queueItemCheck[0];
394
queueItemCheckValue = queueItemCheck[1];
396
if (queueItemCheckKey ==
397
supercedesCheck.toLowerCase() ) {
399
this.eventQueue.push([queueItemCheckKey,
400
queueItemCheckValue]);
402
this.eventQueue[q] = null;
419
* Fires the event for a property using the property's current value.
420
* @method refireEvent
421
* @param {String} key The name of the property
423
refireEvent: function (key) {
425
key = key.toLowerCase();
427
var property = this.config[key];
429
if (property && property.event &&
431
!Lang.isUndefined(property.value)) {
433
if (this.queueInProgress) {
435
this.queueProperty(key);
439
this.fireEvent(key, property.value);
447
* Applies a key-value Object literal to the configuration, replacing
448
* any existing values, and queueing the property events.
449
* Although the values will be set, fireQueue() must be called for their
450
* associated events to execute.
451
* @method applyConfig
452
* @param {Object} userConfig The configuration Object literal
453
* @param {Boolean} init When set to true, the initialConfig will
454
* be set to the userConfig passed in, so that calling a reset will
455
* reset the properties to the passed values.
457
applyConfig: function (userConfig, init) {
464
for (sKey in userConfig) {
465
if (Lang.hasOwnProperty(userConfig, sKey)) {
466
oConfig[sKey.toLowerCase()] = userConfig[sKey];
469
this.initialConfig = oConfig;
472
for (sKey in userConfig) {
473
if (Lang.hasOwnProperty(userConfig, sKey)) {
474
this.queueProperty(sKey, userConfig[sKey]);
480
* Refires the events for all configuration properties using their
484
refresh: function () {
488
for (prop in this.config) {
489
if (Lang.hasOwnProperty(this.config, prop)) {
490
this.refireEvent(prop);
496
* Fires the normalized list of queued property change events
499
fireQueue: function () {
507
this.queueInProgress = true;
508
for (i = 0;i < this.eventQueue.length; i++) {
509
queueItem = this.eventQueue[i];
513
value = queueItem[1];
514
property = this.config[key];
516
property.value = value;
518
// Clear out queue entry, to avoid it being
519
// re-added to the queue by any queueProperty/supercedes
520
// calls which are invoked during fireEvent
521
this.eventQueue[i] = null;
523
this.fireEvent(key,value);
527
this.queueInProgress = false;
528
this.eventQueue = [];
532
* Subscribes an external handler to the change event for any
534
* @method subscribeToConfigEvent
535
* @param {String} key The property name
536
* @param {Function} handler The handler function to use subscribe to
537
* the property's event
538
* @param {Object} obj The Object to use for scoping the event handler
539
* (see CustomEvent documentation)
540
* @param {Boolean} override Optional. If true, will override "this"
541
* within the handler to map to the scope Object passed into the method.
542
* @return {Boolean} True, if the subscription was successful,
545
subscribeToConfigEvent: function (key, handler, obj, override) {
547
var property = this.config[key.toLowerCase()];
549
if (property && property.event) {
550
if (!Config.alreadySubscribed(property.event, handler, obj)) {
551
property.event.subscribe(handler, obj, override);
561
* Unsubscribes an external handler from the change event for any
563
* @method unsubscribeFromConfigEvent
564
* @param {String} key The property name
565
* @param {Function} handler The handler function to use subscribe to
566
* the property's event
567
* @param {Object} obj The Object to use for scoping the event
568
* handler (see CustomEvent documentation)
569
* @return {Boolean} True, if the unsubscription was successful,
572
unsubscribeFromConfigEvent: function (key, handler, obj) {
573
var property = this.config[key.toLowerCase()];
574
if (property && property.event) {
575
return property.event.unsubscribe(handler, obj);
582
* Returns a string representation of the Config object
584
* @return {String} The Config object in string format.
586
toString: function () {
587
var output = "Config";
589
output += " [" + this.owner.toString() + "]";
595
* Returns a string representation of the Config object's current
597
* @method outputEventQueue
598
* @return {String} The string list of CustomEvents currently queued
601
outputEventQueue: function () {
606
nQueue = this.eventQueue.length;
608
for (q = 0; q < nQueue; q++) {
609
queueItem = this.eventQueue[q];
611
output += queueItem[0] + "=" + queueItem[1] + ", ";
618
* Sets all properties to null, unsubscribes all listeners from each
619
* property's change event and all listeners from the configChangedEvent.
622
destroy: function () {
624
var oConfig = this.config,
629
for (sProperty in oConfig) {
631
if (Lang.hasOwnProperty(oConfig, sProperty)) {
633
oProperty = oConfig[sProperty];
635
oProperty.event.unsubscribeAll();
636
oProperty.event = null;
642
this.configChangedEvent.unsubscribeAll();
644
this.configChangedEvent = null;
647
this.initialConfig = null;
648
this.eventQueue = null;
657
* Checks to determine if a particular function/Object pair are already
658
* subscribed to the specified CustomEvent
659
* @method YAHOO.util.Config.alreadySubscribed
661
* @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check
663
* @param {Function} fn The function to look for in the subscribers list
664
* @param {Object} obj The execution scope Object for the subscription
665
* @return {Boolean} true, if the function/Object pair is already subscribed
666
* to the CustomEvent passed in
668
Config.alreadySubscribed = function (evt, fn, obj) {
670
var nSubscribers = evt.subscribers.length,
674
if (nSubscribers > 0) {
675
i = nSubscribers - 1;
677
subsc = evt.subscribers[i];
678
if (subsc && subsc.obj == obj && subsc.fn == fn) {
689
YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
696
* The Container family of components is designed to enable developers to
697
* create different kinds of content-containing modules on the web. Module
698
* and Overlay are the most basic containers, and they can be used directly
699
* or extended to build custom containers. Also part of the Container family
700
* are four UI controls that extend Module and Overlay: Tooltip, Panel,
701
* Dialog, and SimpleDialog.
704
* @requires yahoo, dom, event
705
* @optional dragdrop, animation, button
709
* Module is a JavaScript representation of the Standard Module Format.
710
* Standard Module Format is a simple standard for markup containers where
711
* child nodes representing the header, body, and footer of the content are
712
* denoted using the CSS classes "hd", "bd", and "ft" respectively.
713
* Module is the base class for all other classes in the YUI
715
* @namespace YAHOO.widget
718
* @param {String} el The element ID representing the Module <em>OR</em>
719
* @param {HTMLElement} el The element representing the Module
720
* @param {Object} userConfig The configuration Object literal containing
721
* the configuration that should be set for this module. See configuration
722
* documentation for more details.
724
YAHOO.widget.Module = function (el, userConfig) {
726
this.init(el, userConfig);
731
var Dom = YAHOO.util.Dom,
732
Config = YAHOO.util.Config,
733
Event = YAHOO.util.Event,
734
CustomEvent = YAHOO.util.CustomEvent,
735
Module = YAHOO.widget.Module,
744
* Constant representing the name of the Module's events
745
* @property EVENT_TYPES
751
"BEFORE_INIT": "beforeInit",
754
"BEFORE_RENDER": "beforeRender",
756
"CHANGE_HEADER": "changeHeader",
757
"CHANGE_BODY": "changeBody",
758
"CHANGE_FOOTER": "changeFooter",
759
"CHANGE_CONTENT": "changeContent",
760
"DESTORY": "destroy",
761
"BEFORE_SHOW": "beforeShow",
763
"BEFORE_HIDE": "beforeHide",
768
* Constant representing the Module's configuration properties
769
* @property DEFAULT_CONFIG
779
validator: YAHOO.lang.isBoolean
785
supercedes: ["visible"]
789
key: "monitorresize",
793
"APPEND_TO_DOCUMENT_BODY": {
794
key: "appendtodocumentbody",
800
* Constant representing the prefix path to use for non-secure images
801
* @property YAHOO.widget.Module.IMG_ROOT
806
Module.IMG_ROOT = null;
809
* Constant representing the prefix path to use for securely served images
810
* @property YAHOO.widget.Module.IMG_ROOT_SSL
815
Module.IMG_ROOT_SSL = null;
818
* Constant for the default CSS class name that represents a Module
819
* @property YAHOO.widget.Module.CSS_MODULE
824
Module.CSS_MODULE = "yui-module";
827
* Constant representing the module header
828
* @property YAHOO.widget.Module.CSS_HEADER
833
Module.CSS_HEADER = "hd";
836
* Constant representing the module body
837
* @property YAHOO.widget.Module.CSS_BODY
842
Module.CSS_BODY = "bd";
845
* Constant representing the module footer
846
* @property YAHOO.widget.Module.CSS_FOOTER
851
Module.CSS_FOOTER = "ft";
854
* Constant representing the url for the "src" attribute of the iframe
855
* used to monitor changes to the browser's base font size
856
* @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
861
Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
864
* Constant representing the buffer amount (in pixels) to use when positioning
865
* the text resize monitor offscreen. The resize monitor is positioned
866
* offscreen by an amount eqaul to its offsetHeight + the buffer value.
868
* @property YAHOO.widget.Module.RESIZE_MONITOR_BUFFER
872
// Set to 1, to work around pixel offset in IE8, which increases when zoom is used
873
Module.RESIZE_MONITOR_BUFFER = 1;
876
* Singleton CustomEvent fired when the font size is changed in the browser.
877
* Opera's "zoom" functionality currently does not support text
879
* @event YAHOO.widget.Module.textResizeEvent
881
Module.textResizeEvent = new CustomEvent("textResize");
884
* Helper utility method, which forces a document level
885
* redraw for Opera, which can help remove repaint
886
* irregularities after applying DOM changes.
888
* @method YAHOO.widget.Module.forceDocumentRedraw
891
Module.forceDocumentRedraw = function() {
892
var docEl = document.documentElement;
894
docEl.className += " ";
895
docEl.className = YAHOO.lang.trim(docEl.className);
899
function createModuleTemplate() {
901
if (!m_oModuleTemplate) {
902
m_oModuleTemplate = document.createElement("div");
904
m_oModuleTemplate.innerHTML = ("<div class=\"" +
905
Module.CSS_HEADER + "\"></div>" + "<div class=\"" +
906
Module.CSS_BODY + "\"></div><div class=\"" +
907
Module.CSS_FOOTER + "\"></div>");
909
m_oHeaderTemplate = m_oModuleTemplate.firstChild;
910
m_oBodyTemplate = m_oHeaderTemplate.nextSibling;
911
m_oFooterTemplate = m_oBodyTemplate.nextSibling;
914
return m_oModuleTemplate;
917
function createHeader() {
918
if (!m_oHeaderTemplate) {
919
createModuleTemplate();
921
return (m_oHeaderTemplate.cloneNode(false));
924
function createBody() {
925
if (!m_oBodyTemplate) {
926
createModuleTemplate();
928
return (m_oBodyTemplate.cloneNode(false));
931
function createFooter() {
932
if (!m_oFooterTemplate) {
933
createModuleTemplate();
935
return (m_oFooterTemplate.cloneNode(false));
941
* The class's constructor function
942
* @property contructor
948
* The main module element that contains the header, body, and footer
955
* The header element, denoted with CSS class "hd"
962
* The body element, denoted with CSS class "bd"
969
* The footer element, denoted with CSS class "ft"
976
* The id of the element
983
* A string representing the root path for all images created by
985
* @deprecated It is recommend that any images for a Module be applied
986
* via CSS using the "background-image" property.
987
* @property imageRoot
990
imageRoot: Module.IMG_ROOT,
993
* Initializes the custom events for Module which are fired
994
* automatically at appropriate times by the Module class.
997
initEvents: function () {
999
var SIGNATURE = CustomEvent.LIST;
1002
* CustomEvent fired prior to class initalization.
1003
* @event beforeInitEvent
1004
* @param {class} classRef class reference of the initializing
1005
* class, such as this.beforeInitEvent.fire(Module)
1007
this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT);
1008
this.beforeInitEvent.signature = SIGNATURE;
1011
* CustomEvent fired after class initalization.
1013
* @param {class} classRef class reference of the initializing
1014
* class, such as this.beforeInitEvent.fire(Module)
1016
this.initEvent = this.createEvent(EVENT_TYPES.INIT);
1017
this.initEvent.signature = SIGNATURE;
1020
* CustomEvent fired when the Module is appended to the DOM
1021
* @event appendEvent
1023
this.appendEvent = this.createEvent(EVENT_TYPES.APPEND);
1024
this.appendEvent.signature = SIGNATURE;
1027
* CustomEvent fired before the Module is rendered
1028
* @event beforeRenderEvent
1030
this.beforeRenderEvent = this.createEvent(EVENT_TYPES.BEFORE_RENDER);
1031
this.beforeRenderEvent.signature = SIGNATURE;
1034
* CustomEvent fired after the Module is rendered
1035
* @event renderEvent
1037
this.renderEvent = this.createEvent(EVENT_TYPES.RENDER);
1038
this.renderEvent.signature = SIGNATURE;
1041
* CustomEvent fired when the header content of the Module
1043
* @event changeHeaderEvent
1044
* @param {String/HTMLElement} content String/element representing
1045
* the new header content
1047
this.changeHeaderEvent = this.createEvent(EVENT_TYPES.CHANGE_HEADER);
1048
this.changeHeaderEvent.signature = SIGNATURE;
1051
* CustomEvent fired when the body content of the Module is modified
1052
* @event changeBodyEvent
1053
* @param {String/HTMLElement} content String/element representing
1054
* the new body content
1056
this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY);
1057
this.changeBodyEvent.signature = SIGNATURE;
1060
* CustomEvent fired when the footer content of the Module
1062
* @event changeFooterEvent
1063
* @param {String/HTMLElement} content String/element representing
1064
* the new footer content
1066
this.changeFooterEvent = this.createEvent(EVENT_TYPES.CHANGE_FOOTER);
1067
this.changeFooterEvent.signature = SIGNATURE;
1070
* CustomEvent fired when the content of the Module is modified
1071
* @event changeContentEvent
1073
this.changeContentEvent = this.createEvent(EVENT_TYPES.CHANGE_CONTENT);
1074
this.changeContentEvent.signature = SIGNATURE;
1077
* CustomEvent fired when the Module is destroyed
1078
* @event destroyEvent
1080
this.destroyEvent = this.createEvent(EVENT_TYPES.DESTORY);
1081
this.destroyEvent.signature = SIGNATURE;
1084
* CustomEvent fired before the Module is shown
1085
* @event beforeShowEvent
1087
this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW);
1088
this.beforeShowEvent.signature = SIGNATURE;
1091
* CustomEvent fired after the Module is shown
1094
this.showEvent = this.createEvent(EVENT_TYPES.SHOW);
1095
this.showEvent.signature = SIGNATURE;
1098
* CustomEvent fired before the Module is hidden
1099
* @event beforeHideEvent
1101
this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE);
1102
this.beforeHideEvent.signature = SIGNATURE;
1105
* CustomEvent fired after the Module is hidden
1108
this.hideEvent = this.createEvent(EVENT_TYPES.HIDE);
1109
this.hideEvent.signature = SIGNATURE;
1113
* String representing the current user-agent platform
1114
* @property platform
1117
platform: function () {
1118
var ua = navigator.userAgent.toLowerCase();
1120
if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
1122
} else if (ua.indexOf("macintosh") != -1) {
1130
* String representing the user-agent of the browser
1131
* @deprecated Use YAHOO.env.ua
1135
browser: function () {
1136
var ua = navigator.userAgent.toLowerCase();
1138
Check Opera first in case of spoof and check Safari before
1139
Gecko since Safari's user agent string includes "like Gecko"
1141
if (ua.indexOf('opera') != -1) {
1143
} else if (ua.indexOf('msie 7') != -1) {
1145
} else if (ua.indexOf('msie') != -1) {
1147
} else if (ua.indexOf('safari') != -1) {
1149
} else if (ua.indexOf('gecko') != -1) {
1157
* Boolean representing whether or not the current browsing context is
1159
* @property isSecure
1162
isSecure: function () {
1163
if (window.location.href.toLowerCase().indexOf("https") === 0) {
1171
* Initializes the custom events for Module which are fired
1172
* automatically at appropriate times by the Module class.
1174
initDefaultConfig: function () {
1175
// Add properties //
1177
* Specifies whether the Module is visible on the page.
1182
this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, {
1183
handler: this.configVisible,
1184
value: DEFAULT_CONFIG.VISIBLE.value,
1185
validator: DEFAULT_CONFIG.VISIBLE.validator
1190
* Object or array of objects representing the ContainerEffect
1191
* classes that are active for animating the container.
1194
* <strong>NOTE:</strong> Although this configuration
1195
* property is introduced at the Module level, an out of the box
1196
* implementation is not shipped for the Module class so setting
1197
* the proroperty on the Module class has no effect. The Overlay
1198
* class is the first class to provide out of the box ContainerEffect
1205
this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, {
1206
suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent,
1207
supercedes: DEFAULT_CONFIG.EFFECT.supercedes
1211
* Specifies whether to create a special proxy iframe to monitor
1212
* for user font resizing in the document
1213
* @config monitorresize
1217
this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, {
1218
handler: this.configMonitorResize,
1219
value: DEFAULT_CONFIG.MONITOR_RESIZE.value
1223
* Specifies if the module should be rendered as the first child
1224
* of document.body or appended as the last child when render is called
1225
* with document.body as the "appendToNode".
1227
* Appending to the body while the DOM is still being constructed can
1228
* lead to Operation Aborted errors in IE hence this flag is set to
1232
* @config appendtodocumentbody
1236
this.cfg.addProperty(DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.key, {
1237
value: DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.value
1242
* The Module class's initialization method, which is executed for
1243
* Module and all of its subclasses. This method is automatically
1244
* called by the constructor, and sets up all DOM references for
1245
* pre-existing markup, and creates required markup if it is not
1248
* If the element passed in does not have an id, one will be generated
1252
* @param {String} el The element ID representing the Module <em>OR</em>
1253
* @param {HTMLElement} el The element representing the Module
1254
* @param {Object} userConfig The configuration Object literal
1255
* containing the configuration that should be set for this module.
1256
* See configuration documentation for more details.
1258
init: function (el, userConfig) {
1263
this.beforeInitEvent.fire(Module);
1266
* The Module's Config object used for monitoring
1267
* configuration properties.
1269
* @type YAHOO.util.Config
1271
this.cfg = new Config(this);
1273
if (this.isSecure) {
1274
this.imageRoot = Module.IMG_ROOT_SSL;
1277
if (typeof el == "string") {
1279
el = document.getElementById(el);
1281
el = (createModuleTemplate()).cloneNode(false);
1286
this.id = Dom.generateId(el);
1289
child = this.element.firstChild;
1292
var fndHd = false, fndBd = false, fndFt = false;
1294
// We're looking for elements
1295
if (1 == child.nodeType) {
1296
if (!fndHd && Dom.hasClass(child, Module.CSS_HEADER)) {
1297
this.header = child;
1299
} else if (!fndBd && Dom.hasClass(child, Module.CSS_BODY)) {
1302
} else if (!fndFt && Dom.hasClass(child, Module.CSS_FOOTER)){
1303
this.footer = child;
1307
} while ((child = child.nextSibling));
1310
this.initDefaultConfig();
1312
Dom.addClass(this.element, Module.CSS_MODULE);
1315
this.cfg.applyConfig(userConfig, true);
1319
Subscribe to the fireQueue() method of Config so that any
1320
queued configuration changes are excecuted upon render of
1324
if (!Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) {
1325
this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
1328
this.initEvent.fire(Module);
1332
* Initialize an empty IFRAME that is placed out of the visible area
1333
* that can be used to detect text resize.
1334
* @method initResizeMonitor
1336
initResizeMonitor: function () {
1338
var isGeckoWin = (UA.gecko && this.platform == "windows");
1340
// Help prevent spinning loading icon which
1341
// started with FireFox 2.0.0.8/Win
1343
setTimeout(function(){self._initResizeMonitor();}, 0);
1345
this._initResizeMonitor();
1350
* Create and initialize the text resize monitoring iframe.
1353
* @method _initResizeMonitor
1355
_initResizeMonitor : function() {
1361
function fireTextResize() {
1362
Module.textResizeEvent.fire();
1366
oIFrame = Dom.get("_yuiResizeMonitor");
1368
var supportsCWResize = this._supportsCWResize();
1371
oIFrame = document.createElement("iframe");
1373
if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && UA.ie) {
1374
oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL;
1377
if (!supportsCWResize) {
1378
// Can't monitor on contentWindow, so fire from inside iframe
1379
sHTML = ["<html><head><script ",
1380
"type=\"text/javascript\">",
1381
"window.onresize=function(){window.parent.",
1382
"YAHOO.widget.Module.textResizeEvent.",
1385
"<body></body></html>"].join('');
1387
oIFrame.src = "data:text/html;charset=utf-8," + encodeURIComponent(sHTML);
1390
oIFrame.id = "_yuiResizeMonitor";
1391
oIFrame.title = "Text Resize Monitor";
1393
Need to set "position" property before inserting the
1394
iframe into the document or Safari's status bar will
1395
forever indicate the iframe is loading
1396
(See SourceForge bug #1723064)
1398
oIFrame.style.position = "absolute";
1399
oIFrame.style.visibility = "hidden";
1401
var db = document.body,
1404
db.insertBefore(oIFrame, fc);
1406
db.appendChild(oIFrame);
1409
oIFrame.style.width = "2em";
1410
oIFrame.style.height = "2em";
1411
oIFrame.style.top = (-1 * (oIFrame.offsetHeight + Module.RESIZE_MONITOR_BUFFER)) + "px";
1412
oIFrame.style.left = "0";
1413
oIFrame.style.borderWidth = "0";
1414
oIFrame.style.visibility = "visible";
1417
Don't open/close the document for Gecko like we used to, since it
1418
leads to duplicate cookies. (See SourceForge bug #1721755)
1421
oDoc = oIFrame.contentWindow.document;
1427
if (oIFrame && oIFrame.contentWindow) {
1428
Module.textResizeEvent.subscribe(this.onDomResize, this, true);
1430
if (!Module.textResizeInitialized) {
1431
if (supportsCWResize) {
1432
if (!Event.on(oIFrame.contentWindow, "resize", fireTextResize)) {
1434
This will fail in IE if document.domain has
1435
changed, so we must change the listener to
1436
use the oIFrame element instead
1438
Event.on(oIFrame, "resize", fireTextResize);
1441
Module.textResizeInitialized = true;
1443
this.resizeMonitor = oIFrame;
1449
* Text resize monitor helper method.
1450
* Determines if the browser supports resize events on iframe content windows.
1453
* @method _supportsCWResize
1455
_supportsCWResize : function() {
1457
Gecko 1.8.0 (FF1.5), 1.8.1.0-5 (FF2) won't fire resize on contentWindow.
1458
Gecko 1.8.1.6+ (FF2.0.0.6+) and all other browsers will fire resize on contentWindow.
1460
We don't want to start sniffing for patch versions, so fire textResize the same
1461
way on all FF2 flavors
1463
var bSupported = true;
1464
if (UA.gecko && UA.gecko <= 1.8) {
1471
* Event handler fired when the resize monitor element is resized.
1472
* @method onDomResize
1473
* @param {DOMEvent} e The DOM resize event
1474
* @param {Object} obj The scope object passed to the handler
1476
onDomResize: function (e, obj) {
1478
var nTop = -1 * (this.resizeMonitor.offsetHeight + Module.RESIZE_MONITOR_BUFFER);
1480
this.resizeMonitor.style.top = nTop + "px";
1481
this.resizeMonitor.style.left = "0";
1485
* Sets the Module's header content to the string specified, or appends
1486
* the passed element to the header. If no header is present, one will
1487
* be automatically created. An empty string can be passed to the method
1488
* to clear the contents of the header.
1491
* @param {String} headerContent The string used to set the header.
1492
* As a convenience, non HTMLElement objects can also be passed into
1493
* the method, and will be treated as strings, with the header innerHTML
1494
* set to their default toString implementations.
1496
* @param {HTMLElement} headerContent The HTMLElement to append to
1498
* @param {DocumentFragment} headerContent The document fragment
1499
* containing elements which are to be added to the header
1501
setHeader: function (headerContent) {
1502
var oHeader = this.header || (this.header = createHeader());
1504
if (headerContent.nodeName) {
1505
oHeader.innerHTML = "";
1506
oHeader.appendChild(headerContent);
1508
oHeader.innerHTML = headerContent;
1511
this.changeHeaderEvent.fire(headerContent);
1512
this.changeContentEvent.fire();
1517
* Appends the passed element to the header. If no header is present,
1518
* one will be automatically created.
1519
* @method appendToHeader
1520
* @param {HTMLElement | DocumentFragment} element The element to
1521
* append to the header. In the case of a document fragment, the
1522
* children of the fragment will be appended to the header.
1524
appendToHeader: function (element) {
1525
var oHeader = this.header || (this.header = createHeader());
1527
oHeader.appendChild(element);
1529
this.changeHeaderEvent.fire(element);
1530
this.changeContentEvent.fire();
1535
* Sets the Module's body content to the HTML specified.
1537
* If no body is present, one will be automatically created.
1539
* An empty string can be passed to the method to clear the contents of the body.
1541
* @param {String} bodyContent The HTML used to set the body.
1542
* As a convenience, non HTMLElement objects can also be passed into
1543
* the method, and will be treated as strings, with the body innerHTML
1544
* set to their default toString implementations.
1546
* @param {HTMLElement} bodyContent The HTMLElement to add as the first and only
1547
* child of the body element.
1549
* @param {DocumentFragment} bodyContent The document fragment
1550
* containing elements which are to be added to the body
1552
setBody: function (bodyContent) {
1553
var oBody = this.body || (this.body = createBody());
1555
if (bodyContent.nodeName) {
1556
oBody.innerHTML = "";
1557
oBody.appendChild(bodyContent);
1559
oBody.innerHTML = bodyContent;
1562
this.changeBodyEvent.fire(bodyContent);
1563
this.changeContentEvent.fire();
1567
* Appends the passed element to the body. If no body is present, one
1568
* will be automatically created.
1569
* @method appendToBody
1570
* @param {HTMLElement | DocumentFragment} element The element to
1571
* append to the body. In the case of a document fragment, the
1572
* children of the fragment will be appended to the body.
1575
appendToBody: function (element) {
1576
var oBody = this.body || (this.body = createBody());
1578
oBody.appendChild(element);
1580
this.changeBodyEvent.fire(element);
1581
this.changeContentEvent.fire();
1586
* Sets the Module's footer content to the HTML specified, or appends
1587
* the passed element to the footer. If no footer is present, one will
1588
* be automatically created. An empty string can be passed to the method
1589
* to clear the contents of the footer.
1591
* @param {String} footerContent The HTML used to set the footer
1592
* As a convenience, non HTMLElement objects can also be passed into
1593
* the method, and will be treated as strings, with the footer innerHTML
1594
* set to their default toString implementations.
1596
* @param {HTMLElement} footerContent The HTMLElement to append to
1599
* @param {DocumentFragment} footerContent The document fragment containing
1600
* elements which are to be added to the footer
1602
setFooter: function (footerContent) {
1604
var oFooter = this.footer || (this.footer = createFooter());
1606
if (footerContent.nodeName) {
1607
oFooter.innerHTML = "";
1608
oFooter.appendChild(footerContent);
1610
oFooter.innerHTML = footerContent;
1613
this.changeFooterEvent.fire(footerContent);
1614
this.changeContentEvent.fire();
1618
* Appends the passed element to the footer. If no footer is present,
1619
* one will be automatically created.
1620
* @method appendToFooter
1621
* @param {HTMLElement | DocumentFragment} element The element to
1622
* append to the footer. In the case of a document fragment, the
1623
* children of the fragment will be appended to the footer
1625
appendToFooter: function (element) {
1627
var oFooter = this.footer || (this.footer = createFooter());
1629
oFooter.appendChild(element);
1631
this.changeFooterEvent.fire(element);
1632
this.changeContentEvent.fire();
1637
* Renders the Module by inserting the elements that are not already
1638
* in the main Module into their correct places. Optionally appends
1639
* the Module to the specified node prior to the render's execution.
1641
* For Modules without existing markup, the appendToNode argument
1642
* is REQUIRED. If this argument is ommitted and the current element is
1643
* not present in the document, the function will return false,
1644
* indicating that the render was a failure.
1647
* NOTE: As of 2.3.1, if the appendToNode is the document's body element
1648
* then the module is rendered as the first child of the body element,
1649
* and not appended to it, to avoid Operation Aborted errors in IE when
1650
* rendering the module before window's load event is fired. You can
1651
* use the appendtodocumentbody configuration property to change this
1652
* to append to document.body if required.
1655
* @param {String} appendToNode The element id to which the Module
1656
* should be appended to prior to rendering <em>OR</em>
1657
* @param {HTMLElement} appendToNode The element to which the Module
1658
* should be appended to prior to rendering
1659
* @param {HTMLElement} moduleElement OPTIONAL. The element that
1660
* represents the actual Standard Module container.
1661
* @return {Boolean} Success or failure of the render
1663
render: function (appendToNode, moduleElement) {
1668
function appendTo(parentNode) {
1669
if (typeof parentNode == "string") {
1670
parentNode = document.getElementById(parentNode);
1674
me._addToParent(parentNode, me.element);
1675
me.appendEvent.fire();
1679
this.beforeRenderEvent.fire();
1681
if (! moduleElement) {
1682
moduleElement = this.element;
1686
appendTo(appendToNode);
1688
// No node was passed in. If the element is not already in the Dom, this fails
1689
if (! Dom.inDocument(this.element)) {
1694
// Need to get everything into the DOM if it isn't already
1695
if (this.header && ! Dom.inDocument(this.header)) {
1696
// There is a header, but it's not in the DOM yet. Need to add it.
1697
firstChild = moduleElement.firstChild;
1699
moduleElement.insertBefore(this.header, firstChild);
1701
moduleElement.appendChild(this.header);
1705
if (this.body && ! Dom.inDocument(this.body)) {
1706
// There is a body, but it's not in the DOM yet. Need to add it.
1707
if (this.footer && Dom.isAncestor(this.moduleElement, this.footer)) {
1708
moduleElement.insertBefore(this.body, this.footer);
1710
moduleElement.appendChild(this.body);
1714
if (this.footer && ! Dom.inDocument(this.footer)) {
1715
// There is a footer, but it's not in the DOM yet. Need to add it.
1716
moduleElement.appendChild(this.footer);
1719
this.renderEvent.fire();
1724
* Removes the Module element from the DOM and sets all child elements
1728
destroy: function () {
1733
Event.purgeElement(this.element, true);
1734
parent = this.element.parentNode;
1738
parent.removeChild(this.element);
1741
this.element = null;
1746
Module.textResizeEvent.unsubscribe(this.onDomResize, this);
1751
this.destroyEvent.fire();
1755
* Shows the Module element by setting the visible configuration
1756
* property to true. Also fires two events: beforeShowEvent prior to
1757
* the visibility change, and showEvent after.
1761
this.cfg.setProperty("visible", true);
1765
* Hides the Module element by setting the visible configuration
1766
* property to false. Also fires two events: beforeHideEvent prior to
1767
* the visibility change, and hideEvent after.
1771
this.cfg.setProperty("visible", false);
1774
// BUILT-IN EVENT HANDLERS FOR MODULE //
1776
* Default event handler for changing the visibility property of a
1777
* Module. By default, this is achieved by switching the "display" style
1778
* between "block" and "none".
1779
* This method is responsible for firing showEvent and hideEvent.
1780
* @param {String} type The CustomEvent type (usually the property name)
1781
* @param {Object[]} args The CustomEvent arguments. For configuration
1782
* handlers, args[0] will equal the newly applied value for the property.
1783
* @param {Object} obj The scope object. For configuration handlers,
1784
* this will usually equal the owner.
1785
* @method configVisible
1787
configVisible: function (type, args, obj) {
1788
var visible = args[0];
1790
this.beforeShowEvent.fire();
1791
Dom.setStyle(this.element, "display", "block");
1792
this.showEvent.fire();
1794
this.beforeHideEvent.fire();
1795
Dom.setStyle(this.element, "display", "none");
1796
this.hideEvent.fire();
1801
* Default event handler for the "monitorresize" configuration property
1802
* @param {String} type The CustomEvent type (usually the property name)
1803
* @param {Object[]} args The CustomEvent arguments. For configuration
1804
* handlers, args[0] will equal the newly applied value for the property.
1805
* @param {Object} obj The scope object. For configuration handlers,
1806
* this will usually equal the owner.
1807
* @method configMonitorResize
1809
configMonitorResize: function (type, args, obj) {
1810
var monitor = args[0];
1812
this.initResizeMonitor();
1814
Module.textResizeEvent.unsubscribe(this.onDomResize, this, true);
1815
this.resizeMonitor = null;
1820
* This method is a protected helper, used when constructing the DOM structure for the module
1821
* to account for situations which may cause Operation Aborted errors in IE. It should not
1822
* be used for general DOM construction.
1824
* If the parentNode is not document.body, the element is appended as the last element.
1827
* If the parentNode is document.body the element is added as the first child to help
1828
* prevent Operation Aborted errors in IE.
1831
* @param {parentNode} The HTML element to which the element will be added
1832
* @param {element} The HTML element to be added to parentNode's children
1833
* @method _addToParent
1836
_addToParent: function(parentNode, element) {
1837
if (!this.cfg.getProperty("appendtodocumentbody") && parentNode === document.body && parentNode.firstChild) {
1838
parentNode.insertBefore(element, parentNode.firstChild);
1840
parentNode.appendChild(element);
1845
* Returns a String representation of the Object.
1847
* @return {String} The string representation of the Module
1849
toString: function () {
1850
return "Module " + this.id;
1854
YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
1861
* Overlay is a Module that is absolutely positioned above the page flow. It
1862
* has convenience methods for positioning and sizing, as well as options for
1863
* controlling zIndex and constraining the Overlay's position to the current
1864
* visible viewport. Overlay also contains a dynamicly generated IFRAME which
1865
* is placed beneath it for Internet Explorer 6 and 5.x so that it will be
1866
* properly rendered above SELECT elements.
1867
* @namespace YAHOO.widget
1869
* @extends YAHOO.widget.Module
1870
* @param {String} el The element ID representing the Overlay <em>OR</em>
1871
* @param {HTMLElement} el The element representing the Overlay
1872
* @param {Object} userConfig The configuration object literal containing
1873
* the configuration that should be set for this Overlay. See configuration
1874
* documentation for more details.
1877
YAHOO.widget.Overlay = function (el, userConfig) {
1878
YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
1881
var Lang = YAHOO.lang,
1882
CustomEvent = YAHOO.util.CustomEvent,
1883
Module = YAHOO.widget.Module,
1884
Event = YAHOO.util.Event,
1885
Dom = YAHOO.util.Dom,
1886
Config = YAHOO.util.Config,
1888
Overlay = YAHOO.widget.Overlay,
1890
_SUBSCRIBE = "subscribe",
1891
_UNSUBSCRIBE = "unsubscribe",
1892
_CONTAINED = "contained",
1897
* Constant representing the name of the Overlay's events
1898
* @property EVENT_TYPES
1904
"BEFORE_MOVE": "beforeMove",
1909
* Constant representing the Overlay's configuration properties
1910
* @property DEFAULT_CONFIG
1919
validator: Lang.isNumber,
1920
suppressEvent: true,
1921
supercedes: ["iframe"]
1926
validator: Lang.isNumber,
1927
suppressEvent: true,
1928
supercedes: ["iframe"]
1933
suppressEvent: true,
1934
supercedes: ["iframe"]
1939
suppressEvent: true,
1940
supercedes: ["iframe"]
1946
supercedes: ["iframe", "visible"]
1951
suppressEvent: true,
1952
supercedes: ["context", "fixedcenter", "iframe"]
1957
suppressEvent: true,
1958
supercedes: ["context", "fixedcenter", "iframe"]
1961
"AUTO_FILL_HEIGHT" : {
1962
key: "autofillheight",
1963
supercedes: ["height"],
1972
"CONSTRAIN_TO_VIEWPORT": {
1973
key: "constraintoviewport",
1975
validator: Lang.isBoolean,
1976
supercedes: ["iframe", "x", "y", "xy"]
1981
value: (UA.ie == 6 ? true : false),
1982
validator: Lang.isBoolean,
1983
supercedes: ["zindex"]
1986
"PREVENT_CONTEXT_OVERLAP": {
1987
key: "preventcontextoverlap",
1989
validator: Lang.isBoolean,
1990
supercedes: ["constraintoviewport"]
1996
* The URL that will be placed in the iframe
1997
* @property YAHOO.widget.Overlay.IFRAME_SRC
2002
Overlay.IFRAME_SRC = "javascript:false;";
2005
* Number representing how much the iframe shim should be offset from each
2006
* side of an Overlay instance, in pixels.
2007
* @property YAHOO.widget.Overlay.IFRAME_SRC
2013
Overlay.IFRAME_OFFSET = 3;
2016
* Number representing the minimum distance an Overlay instance should be
2017
* positioned relative to the boundaries of the browser's viewport, in pixels.
2018
* @property YAHOO.widget.Overlay.VIEWPORT_OFFSET
2024
Overlay.VIEWPORT_OFFSET = 10;
2027
* Constant representing the top left corner of an element, used for
2028
* configuring the context element alignment
2029
* @property YAHOO.widget.Overlay.TOP_LEFT
2034
Overlay.TOP_LEFT = "tl";
2037
* Constant representing the top right corner of an element, used for
2038
* configuring the context element alignment
2039
* @property YAHOO.widget.Overlay.TOP_RIGHT
2044
Overlay.TOP_RIGHT = "tr";
2047
* Constant representing the top bottom left corner of an element, used for
2048
* configuring the context element alignment
2049
* @property YAHOO.widget.Overlay.BOTTOM_LEFT
2054
Overlay.BOTTOM_LEFT = "bl";
2057
* Constant representing the bottom right corner of an element, used for
2058
* configuring the context element alignment
2059
* @property YAHOO.widget.Overlay.BOTTOM_RIGHT
2064
Overlay.BOTTOM_RIGHT = "br";
2067
* Constant representing the default CSS class used for an Overlay
2068
* @property YAHOO.widget.Overlay.CSS_OVERLAY
2073
Overlay.CSS_OVERLAY = "yui-overlay";
2076
* Constant representing the names of the standard module elements
2077
* used in the overlay.
2078
* @property YAHOO.widget.Overlay.STD_MOD_RE
2083
Overlay.STD_MOD_RE = /^\s*?(body|footer|header)\s*?$/i;
2086
* A singleton CustomEvent used for reacting to the DOM event for
2088
* @event YAHOO.widget.Overlay.windowScrollEvent
2090
Overlay.windowScrollEvent = new CustomEvent("windowScroll");
2093
* A singleton CustomEvent used for reacting to the DOM event for
2095
* @event YAHOO.widget.Overlay.windowResizeEvent
2097
Overlay.windowResizeEvent = new CustomEvent("windowResize");
2100
* The DOM event handler used to fire the CustomEvent for window scroll
2101
* @method YAHOO.widget.Overlay.windowScrollHandler
2103
* @param {DOMEvent} e The DOM scroll event
2105
Overlay.windowScrollHandler = function (e) {
2106
var t = Event.getTarget(e);
2108
// - Webkit (Safari 2/3) and Opera 9.2x bubble scroll events from elements to window
2109
// - FF2/3 and IE6/7, Opera 9.5x don't bubble scroll events from elements to window
2110
// - IE doesn't recognize scroll registered on the document.
2112
// Also, when document view is scrolled, IE doesn't provide a target,
2113
// rest of the browsers set target to window.document, apart from opera
2114
// which sets target to window.
2115
if (!t || t === window || t === window.document) {
2118
if (! window.scrollEnd) {
2119
window.scrollEnd = -1;
2122
clearTimeout(window.scrollEnd);
2124
window.scrollEnd = setTimeout(function () {
2125
Overlay.windowScrollEvent.fire();
2129
Overlay.windowScrollEvent.fire();
2135
* The DOM event handler used to fire the CustomEvent for window resize
2136
* @method YAHOO.widget.Overlay.windowResizeHandler
2138
* @param {DOMEvent} e The DOM resize event
2140
Overlay.windowResizeHandler = function (e) {
2143
if (! window.resizeEnd) {
2144
window.resizeEnd = -1;
2147
clearTimeout(window.resizeEnd);
2149
window.resizeEnd = setTimeout(function () {
2150
Overlay.windowResizeEvent.fire();
2153
Overlay.windowResizeEvent.fire();
2158
* A boolean that indicated whether the window resize and scroll events have
2159
* already been subscribed to.
2160
* @property YAHOO.widget.Overlay._initialized
2164
Overlay._initialized = null;
2166
if (Overlay._initialized === null) {
2167
Event.on(window, "scroll", Overlay.windowScrollHandler);
2168
Event.on(window, "resize", Overlay.windowResizeHandler);
2169
Overlay._initialized = true;
2173
* Internal map of special event types, which are provided
2174
* by the instance. It maps the event type to the custom event
2175
* instance. Contains entries for the "windowScroll", "windowResize" and
2176
* "textResize" static container events.
2178
* @property YAHOO.widget.Overlay._TRIGGER_MAP
2183
Overlay._TRIGGER_MAP = {
2184
"windowScroll" : Overlay.windowScrollEvent,
2185
"windowResize" : Overlay.windowResizeEvent,
2186
"textResize" : Module.textResizeEvent
2189
YAHOO.extend(Overlay, Module, {
2193
* Array of default event types which will trigger
2194
* context alignment for the Overlay class.
2196
* <p>The array is empty by default for Overlay,
2197
* but maybe populated in future releases, so classes extending
2198
* Overlay which need to define their own set of CONTEXT_TRIGGERS
2199
* should concatenate their super class's prototype.CONTEXT_TRIGGERS
2200
* value with their own array of values.
2204
* <code>CustomOverlay.prototype.CONTEXT_TRIGGERS = YAHOO.widget.Overlay.prototype.CONTEXT_TRIGGERS.concat(["windowScroll"]);</code>
2207
* @property CONTEXT_TRIGGERS
2211
CONTEXT_TRIGGERS : [],
2214
* The Overlay initialization method, which is executed for Overlay and
2215
* all of its subclasses. This method is automatically called by the
2216
* constructor, and sets up all DOM references for pre-existing markup,
2217
* and creates required markup if it is not already present.
2219
* @param {String} el The element ID representing the Overlay <em>OR</em>
2220
* @param {HTMLElement} el The element representing the Overlay
2221
* @param {Object} userConfig The configuration object literal
2222
* containing the configuration that should be set for this Overlay.
2223
* See configuration documentation for more details.
2225
init: function (el, userConfig) {
2228
Note that we don't pass the user config in here yet because we
2229
only want it executed once, at the lowest subclass level
2232
Overlay.superclass.init.call(this, el/*, userConfig*/);
2234
this.beforeInitEvent.fire(Overlay);
2236
Dom.addClass(this.element, Overlay.CSS_OVERLAY);
2239
this.cfg.applyConfig(userConfig, true);
2242
if (this.platform == "mac" && UA.gecko) {
2244
if (! Config.alreadySubscribed(this.showEvent,
2245
this.showMacGeckoScrollbars, this)) {
2247
this.showEvent.subscribe(this.showMacGeckoScrollbars,
2252
if (! Config.alreadySubscribed(this.hideEvent,
2253
this.hideMacGeckoScrollbars, this)) {
2255
this.hideEvent.subscribe(this.hideMacGeckoScrollbars,
2261
this.initEvent.fire(Overlay);
2265
* Initializes the custom events for Overlay which are fired
2266
* automatically at appropriate times by the Overlay class.
2267
* @method initEvents
2269
initEvents: function () {
2271
Overlay.superclass.initEvents.call(this);
2273
var SIGNATURE = CustomEvent.LIST;
2276
* CustomEvent fired before the Overlay is moved.
2277
* @event beforeMoveEvent
2278
* @param {Number} x x coordinate
2279
* @param {Number} y y coordinate
2281
this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
2282
this.beforeMoveEvent.signature = SIGNATURE;
2285
* CustomEvent fired after the Overlay is moved.
2287
* @param {Number} x x coordinate
2288
* @param {Number} y y coordinate
2290
this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
2291
this.moveEvent.signature = SIGNATURE;
2296
* Initializes the class's configurable properties which can be changed
2297
* using the Overlay's Config object (cfg).
2298
* @method initDefaultConfig
2300
initDefaultConfig: function () {
2302
Overlay.superclass.initDefaultConfig.call(this);
2306
// Add overlay config properties //
2309
* The absolute x-coordinate position of the Overlay
2314
cfg.addProperty(DEFAULT_CONFIG.X.key, {
2316
handler: this.configX,
2317
validator: DEFAULT_CONFIG.X.validator,
2318
suppressEvent: DEFAULT_CONFIG.X.suppressEvent,
2319
supercedes: DEFAULT_CONFIG.X.supercedes
2324
* The absolute y-coordinate position of the Overlay
2329
cfg.addProperty(DEFAULT_CONFIG.Y.key, {
2331
handler: this.configY,
2332
validator: DEFAULT_CONFIG.Y.validator,
2333
suppressEvent: DEFAULT_CONFIG.Y.suppressEvent,
2334
supercedes: DEFAULT_CONFIG.Y.supercedes
2339
* An array with the absolute x and y positions of the Overlay
2344
cfg.addProperty(DEFAULT_CONFIG.XY.key, {
2345
handler: this.configXY,
2346
suppressEvent: DEFAULT_CONFIG.XY.suppressEvent,
2347
supercedes: DEFAULT_CONFIG.XY.supercedes
2352
* The array of context arguments for context-sensitive positioning.
2356
* The format of the array is: <code>[contextElementOrId, overlayCorner, contextCorner, arrayOfTriggerEvents (optional)]</code>, the
2357
* the 4 array elements described in detail below:
2361
* <dt>contextElementOrId <String|HTMLElement></dt>
2362
* <dd>A reference to the context element to which the overlay should be aligned (or it's id).</dd>
2363
* <dt>overlayCorner <String></dt>
2364
* <dd>The corner of the overlay which is to be used for alignment. This corner will be aligned to the
2365
* corner of the context element defined by the "contextCorner" entry which follows. Supported string values are:
2366
* "tr" (top right), "tl" (top left), "br" (bottom right), or "bl" (bottom left).</dd>
2367
* <dt>contextCorner <String></dt>
2368
* <dd>The corner of the context element which is to be used for alignment. Supported string values are the same ones listed for the "overlayCorner" entry above.</dd>
2369
* <dt>arrayOfTriggerEvents (optional) <Array[String|CustomEvent]></dt>
2372
* By default, context alignment is a one time operation, aligning the Overlay to the context element when context configuration property is set, or when the <a href="#method_align">align</a>
2373
* method is invoked. However, you can use the optional "arrayOfTriggerEvents" entry to define the list of events which should force the overlay to re-align itself with the context element.
2374
* This is useful in situations where the layout of the document may change, resulting in the context element's position being modified.
2377
* The array can contain either event type strings for events the instance publishes (e.g. "beforeShow") or CustomEvent instances. Additionally the following
2378
* 3 static container event types are also currently supported : <code>"windowResize", "windowScroll", "textResize"</code> (defined in <a href="#property__TRIGGER_MAP">_TRIGGER_MAP</a> private property).
2384
* For example, setting this property to <code>["img1", "tl", "bl"]</code> will
2385
* align the Overlay's top left corner to the bottom left corner of the
2386
* context element with id "img1".
2389
* Adding the optional trigger values: <code>["img1", "tl", "bl", ["beforeShow", "windowResize"]]</code>,
2390
* will re-align the overlay position, whenever the "beforeShow" or "windowResize" events are fired.
2397
cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
2398
handler: this.configContext,
2399
suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent,
2400
supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
2404
* Determines whether or not the Overlay should be anchored
2405
* to the center of the viewport.
2407
* <p>This property can be set to:</p>
2412
* To enable fixed center positioning
2414
* When enabled, the overlay will
2415
* be positioned in the center of viewport when initially displayed, and
2416
* will remain in the center of the viewport whenever the window is
2417
* scrolled or resized.
2420
* If the overlay is too big for the viewport,
2421
* it's top left corner will be aligned with the top left corner of the viewport.
2426
* To disable fixed center positioning.
2427
* <p>In this case the overlay can still be
2428
* centered as a one-off operation, by invoking the <code>center()</code> method,
2429
* however it will not remain centered when the window is scrolled/resized.
2431
* <dt>"contained"<dt>
2432
* <dd>To enable fixed center positioning, as with the <code>true</code> option.
2433
* <p>However, unlike setting the property to <code>true</code>,
2434
* when the property is set to <code>"contained"</code>, if the overlay is
2435
* too big for the viewport, it will not get automatically centered when the
2436
* user scrolls or resizes the window (until the window is large enough to contain the
2437
* overlay). This is useful in cases where the Overlay has both header and footer
2438
* UI controls which the user may need to access.
2443
* @config fixedcenter
2444
* @type Boolean | String
2447
cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
2448
handler: this.configFixedCenter,
2449
value: DEFAULT_CONFIG.FIXED_CENTER.value,
2450
validator: DEFAULT_CONFIG.FIXED_CENTER.validator,
2451
supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
2455
* CSS width of the Overlay.
2460
cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
2461
handler: this.configWidth,
2462
suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent,
2463
supercedes: DEFAULT_CONFIG.WIDTH.supercedes
2467
* CSS height of the Overlay.
2472
cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
2473
handler: this.configHeight,
2474
suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent,
2475
supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
2479
* Standard module element which should auto fill out the height of the Overlay if the height config property is set.
2480
* Supported values are "header", "body", "footer".
2482
* @config autofillheight
2486
cfg.addProperty(DEFAULT_CONFIG.AUTO_FILL_HEIGHT.key, {
2487
handler: this.configAutoFillHeight,
2488
value : DEFAULT_CONFIG.AUTO_FILL_HEIGHT.value,
2489
validator : this._validateAutoFill,
2490
supercedes: DEFAULT_CONFIG.AUTO_FILL_HEIGHT.supercedes
2494
* CSS z-index of the Overlay.
2499
cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
2500
handler: this.configzIndex,
2501
value: DEFAULT_CONFIG.ZINDEX.value
2505
* True if the Overlay should be prevented from being positioned
2506
* out of the viewport.
2507
* @config constraintoviewport
2511
cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
2513
handler: this.configConstrainToViewport,
2514
value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value,
2515
validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator,
2516
supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
2522
* @description Boolean indicating whether or not the Overlay should
2523
* have an IFRAME shim; used to prevent SELECT elements from
2524
* poking through an Overlay instance in IE6. When set to "true",
2525
* the iframe shim is created when the Overlay instance is intially
2528
* @default true for IE6 and below, false for all other browsers.
2530
cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
2532
handler: this.configIframe,
2533
value: DEFAULT_CONFIG.IFRAME.value,
2534
validator: DEFAULT_CONFIG.IFRAME.validator,
2535
supercedes: DEFAULT_CONFIG.IFRAME.supercedes
2540
* @config preventcontextoverlap
2541
* @description Boolean indicating whether or not the Overlay should overlap its
2542
* context element (defined using the "context" configuration property) when the
2543
* "constraintoviewport" configuration property is set to "true".
2547
cfg.addProperty(DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.key, {
2549
value: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.value,
2550
validator: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.validator,
2551
supercedes: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.supercedes
2558
* Moves the Overlay to the specified position. This function is
2559
* identical to calling this.cfg.setProperty("xy", [x,y]);
2561
* @param {Number} x The Overlay's new x position
2562
* @param {Number} y The Overlay's new y position
2564
moveTo: function (x, y) {
2565
this.cfg.setProperty("xy", [x, y]);
2569
* Adds a CSS class ("hide-scrollbars") and removes a CSS class
2570
* ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X
2571
* (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2572
* @method hideMacGeckoScrollbars
2574
hideMacGeckoScrollbars: function () {
2575
Dom.replaceClass(this.element, "show-scrollbars", "hide-scrollbars");
2579
* Adds a CSS class ("show-scrollbars") and removes a CSS class
2580
* ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X
2581
* (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2582
* @method showMacGeckoScrollbars
2584
showMacGeckoScrollbars: function () {
2585
Dom.replaceClass(this.element, "hide-scrollbars", "show-scrollbars");
2589
* Internal implementation to set the visibility of the overlay in the DOM.
2591
* @method _setDomVisibility
2592
* @param {boolean} visible Whether to show or hide the Overlay's outer element
2595
_setDomVisibility : function(show) {
2596
Dom.setStyle(this.element, "visibility", (show) ? "visible" : "hidden");
2599
Dom.removeClass(this.element, "yui-overlay-hidden");
2601
Dom.addClass(this.element, "yui-overlay-hidden");
2605
// BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
2607
* The default event handler fired when the "visible" property is
2608
* changed. This method is responsible for firing showEvent
2610
* @method configVisible
2611
* @param {String} type The CustomEvent type (usually the property name)
2612
* @param {Object[]} args The CustomEvent arguments. For configuration
2613
* handlers, args[0] will equal the newly applied value for the property.
2614
* @param {Object} obj The scope object. For configuration handlers,
2615
* this will usually equal the owner.
2617
configVisible: function (type, args, obj) {
2619
var visible = args[0],
2620
currentVis = Dom.getStyle(this.element, "visibility"),
2621
effect = this.cfg.getProperty("effect"),
2622
effectInstances = [],
2623
isMacGecko = (this.platform == "mac" && UA.gecko),
2624
alreadySubscribed = Config.alreadySubscribed,
2625
eff, ei, e, i, j, k, h,
2629
if (currentVis == "inherit") {
2630
e = this.element.parentNode;
2632
while (e.nodeType != 9 && e.nodeType != 11) {
2633
currentVis = Dom.getStyle(e, "visibility");
2635
if (currentVis != "inherit") {
2642
if (currentVis == "inherit") {
2643
currentVis = "visible";
2648
if (effect instanceof Array) {
2649
nEffects = effect.length;
2651
for (i = 0; i < nEffects; i++) {
2653
effectInstances[effectInstances.length] =
2654
eff.effect(this, eff.duration);
2658
effectInstances[effectInstances.length] =
2659
effect.effect(this, effect.duration);
2663
if (visible) { // Show
2665
this.showMacGeckoScrollbars();
2668
if (effect) { // Animate in
2669
if (visible) { // Animate in if not showing
2670
if (currentVis != "visible" || currentVis === "") {
2671
this.beforeShowEvent.fire();
2672
nEffectInstances = effectInstances.length;
2674
for (j = 0; j < nEffectInstances; j++) {
2675
ei = effectInstances[j];
2676
if (j === 0 && !alreadySubscribed(
2677
ei.animateInCompleteEvent,
2678
this.showEvent.fire, this.showEvent)) {
2681
Delegate showEvent until end
2682
of animateInComplete
2685
ei.animateInCompleteEvent.subscribe(
2686
this.showEvent.fire, this.showEvent, true);
2693
if (currentVis != "visible" || currentVis === "") {
2694
this.beforeShowEvent.fire();
2696
this._setDomVisibility(true);
2698
this.cfg.refireEvent("iframe");
2699
this.showEvent.fire();
2701
this._setDomVisibility(true);
2707
this.hideMacGeckoScrollbars();
2710
if (effect) { // Animate out if showing
2711
if (currentVis == "visible") {
2712
this.beforeHideEvent.fire();
2714
nEffectInstances = effectInstances.length;
2715
for (k = 0; k < nEffectInstances; k++) {
2716
h = effectInstances[k];
2718
if (k === 0 && !alreadySubscribed(
2719
h.animateOutCompleteEvent, this.hideEvent.fire,
2723
Delegate hideEvent until end
2724
of animateOutComplete
2727
h.animateOutCompleteEvent.subscribe(
2728
this.hideEvent.fire, this.hideEvent, true);
2734
} else if (currentVis === "") {
2735
this._setDomVisibility(false);
2738
} else { // Simple hide
2740
if (currentVis == "visible" || currentVis === "") {
2741
this.beforeHideEvent.fire();
2742
this._setDomVisibility(false);
2743
this.hideEvent.fire();
2745
this._setDomVisibility(false);
2752
* Fixed center event handler used for centering on scroll/resize, but only if
2753
* the overlay is visible and, if "fixedcenter" is set to "contained", only if
2754
* the overlay fits within the viewport.
2756
* @method doCenterOnDOMEvent
2758
doCenterOnDOMEvent: function () {
2760
fc = cfg.getProperty("fixedcenter");
2762
if (cfg.getProperty("visible")) {
2763
if (fc && (fc !== _CONTAINED || this.fitsInViewport())) {
2770
* Determines if the Overlay (including the offset value defined by Overlay.VIEWPORT_OFFSET)
2771
* will fit entirely inside the viewport, in both dimensions - width and height.
2773
* @method fitsInViewport
2774
* @return boolean true if the Overlay will fit, false if not
2776
fitsInViewport : function() {
2777
var nViewportOffset = Overlay.VIEWPORT_OFFSET,
2778
element = this.element,
2779
elementWidth = element.offsetWidth,
2780
elementHeight = element.offsetHeight,
2781
viewportWidth = Dom.getViewportWidth(),
2782
viewportHeight = Dom.getViewportHeight();
2784
return ((elementWidth + nViewportOffset < viewportWidth) && (elementHeight + nViewportOffset < viewportHeight));
2788
* The default event handler fired when the "fixedcenter" property
2790
* @method configFixedCenter
2791
* @param {String} type The CustomEvent type (usually the property name)
2792
* @param {Object[]} args The CustomEvent arguments. For configuration
2793
* handlers, args[0] will equal the newly applied value for the property.
2794
* @param {Object} obj The scope object. For configuration handlers,
2795
* this will usually equal the owner.
2797
configFixedCenter: function (type, args, obj) {
2800
alreadySubscribed = Config.alreadySubscribed,
2801
windowResizeEvent = Overlay.windowResizeEvent,
2802
windowScrollEvent = Overlay.windowScrollEvent;
2807
if (!alreadySubscribed(this.beforeShowEvent, this.center)) {
2808
this.beforeShowEvent.subscribe(this.center);
2811
if (!alreadySubscribed(windowResizeEvent, this.doCenterOnDOMEvent, this)) {
2812
windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2815
if (!alreadySubscribed(windowScrollEvent, this.doCenterOnDOMEvent, this)) {
2816
windowScrollEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2820
this.beforeShowEvent.unsubscribe(this.center);
2822
windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2823
windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2828
* The default event handler fired when the "height" property is changed.
2829
* @method configHeight
2830
* @param {String} type The CustomEvent type (usually the property name)
2831
* @param {Object[]} args The CustomEvent arguments. For configuration
2832
* handlers, args[0] will equal the newly applied value for the property.
2833
* @param {Object} obj The scope object. For configuration handlers,
2834
* this will usually equal the owner.
2836
configHeight: function (type, args, obj) {
2838
var height = args[0],
2841
Dom.setStyle(el, "height", height);
2842
this.cfg.refireEvent("iframe");
2846
* The default event handler fired when the "autofillheight" property is changed.
2847
* @method configAutoFillHeight
2849
* @param {String} type The CustomEvent type (usually the property name)
2850
* @param {Object[]} args The CustomEvent arguments. For configuration
2851
* handlers, args[0] will equal the newly applied value for the property.
2852
* @param {Object} obj The scope object. For configuration handlers,
2853
* this will usually equal the owner.
2855
configAutoFillHeight: function (type, args, obj) {
2856
var fillEl = args[0],
2858
autoFillHeight = "autofillheight",
2860
currEl = cfg.getProperty(autoFillHeight),
2861
autoFill = this._autoFillOnHeightChange;
2863
cfg.unsubscribeFromConfigEvent(height, autoFill);
2864
Module.textResizeEvent.unsubscribe(autoFill);
2865
this.changeContentEvent.unsubscribe(autoFill);
2867
if (currEl && fillEl !== currEl && this[currEl]) {
2868
Dom.setStyle(this[currEl], height, "");
2872
fillEl = Lang.trim(fillEl.toLowerCase());
2874
cfg.subscribeToConfigEvent(height, autoFill, this[fillEl], this);
2875
Module.textResizeEvent.subscribe(autoFill, this[fillEl], this);
2876
this.changeContentEvent.subscribe(autoFill, this[fillEl], this);
2878
cfg.setProperty(autoFillHeight, fillEl, true);
2883
* The default event handler fired when the "width" property is changed.
2884
* @method configWidth
2885
* @param {String} type The CustomEvent type (usually the property name)
2886
* @param {Object[]} args The CustomEvent arguments. For configuration
2887
* handlers, args[0] will equal the newly applied value for the property.
2888
* @param {Object} obj The scope object. For configuration handlers,
2889
* this will usually equal the owner.
2891
configWidth: function (type, args, obj) {
2893
var width = args[0],
2896
Dom.setStyle(el, "width", width);
2897
this.cfg.refireEvent("iframe");
2901
* The default event handler fired when the "zIndex" property is changed.
2902
* @method configzIndex
2903
* @param {String} type The CustomEvent type (usually the property name)
2904
* @param {Object[]} args The CustomEvent arguments. For configuration
2905
* handlers, args[0] will equal the newly applied value for the property.
2906
* @param {Object} obj The scope object. For configuration handlers,
2907
* this will usually equal the owner.
2909
configzIndex: function (type, args, obj) {
2911
var zIndex = args[0],
2915
zIndex = Dom.getStyle(el, "zIndex");
2916
if (! zIndex || isNaN(zIndex)) {
2921
if (this.iframe || this.cfg.getProperty("iframe") === true) {
2927
Dom.setStyle(el, "zIndex", zIndex);
2928
this.cfg.setProperty("zIndex", zIndex, true);
2936
* The default event handler fired when the "xy" property is changed.
2938
* @param {String} type The CustomEvent type (usually the property name)
2939
* @param {Object[]} args The CustomEvent arguments. For configuration
2940
* handlers, args[0] will equal the newly applied value for the property.
2941
* @param {Object} obj The scope object. For configuration handlers,
2942
* this will usually equal the owner.
2944
configXY: function (type, args, obj) {
2950
this.cfg.setProperty("x", x);
2951
this.cfg.setProperty("y", y);
2953
this.beforeMoveEvent.fire([x, y]);
2955
x = this.cfg.getProperty("x");
2956
y = this.cfg.getProperty("y");
2959
this.cfg.refireEvent("iframe");
2960
this.moveEvent.fire([x, y]);
2964
* The default event handler fired when the "x" property is changed.
2966
* @param {String} type The CustomEvent type (usually the property name)
2967
* @param {Object[]} args The CustomEvent arguments. For configuration
2968
* handlers, args[0] will equal the newly applied value for the property.
2969
* @param {Object} obj The scope object. For configuration handlers,
2970
* this will usually equal the owner.
2972
configX: function (type, args, obj) {
2975
y = this.cfg.getProperty("y");
2977
this.cfg.setProperty("x", x, true);
2978
this.cfg.setProperty("y", y, true);
2980
this.beforeMoveEvent.fire([x, y]);
2982
x = this.cfg.getProperty("x");
2983
y = this.cfg.getProperty("y");
2985
Dom.setX(this.element, x, true);
2987
this.cfg.setProperty("xy", [x, y], true);
2989
this.cfg.refireEvent("iframe");
2990
this.moveEvent.fire([x, y]);
2994
* The default event handler fired when the "y" property is changed.
2996
* @param {String} type The CustomEvent type (usually the property name)
2997
* @param {Object[]} args The CustomEvent arguments. For configuration
2998
* handlers, args[0] will equal the newly applied value for the property.
2999
* @param {Object} obj The scope object. For configuration handlers,
3000
* this will usually equal the owner.
3002
configY: function (type, args, obj) {
3004
var x = this.cfg.getProperty("x"),
3007
this.cfg.setProperty("x", x, true);
3008
this.cfg.setProperty("y", y, true);
3010
this.beforeMoveEvent.fire([x, y]);
3012
x = this.cfg.getProperty("x");
3013
y = this.cfg.getProperty("y");
3015
Dom.setY(this.element, y, true);
3017
this.cfg.setProperty("xy", [x, y], true);
3019
this.cfg.refireEvent("iframe");
3020
this.moveEvent.fire([x, y]);
3024
* Shows the iframe shim, if it has been enabled.
3025
* @method showIframe
3027
showIframe: function () {
3029
var oIFrame = this.iframe,
3033
oParentNode = this.element.parentNode;
3035
if (oParentNode != oIFrame.parentNode) {
3036
this._addToParent(oParentNode, oIFrame);
3038
oIFrame.style.display = "block";
3043
* Hides the iframe shim, if it has been enabled.
3044
* @method hideIframe
3046
hideIframe: function () {
3048
this.iframe.style.display = "none";
3053
* Syncronizes the size and position of iframe shim to that of its
3054
* corresponding Overlay instance.
3055
* @method syncIframe
3057
syncIframe: function () {
3059
var oIFrame = this.iframe,
3060
oElement = this.element,
3061
nOffset = Overlay.IFRAME_OFFSET,
3062
nDimensionOffset = (nOffset * 2),
3067
oIFrame.style.width = (oElement.offsetWidth + nDimensionOffset + "px");
3068
oIFrame.style.height = (oElement.offsetHeight + nDimensionOffset + "px");
3070
// Position <iframe>
3071
aXY = this.cfg.getProperty("xy");
3073
if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
3074
this.syncPosition();
3075
aXY = this.cfg.getProperty("xy");
3077
Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
3082
* Sets the zindex of the iframe shim, if it exists, based on the zindex of
3083
* the Overlay element. The zindex of the iframe is set to be one less
3084
* than the Overlay element's zindex.
3086
* <p>NOTE: This method will not bump up the zindex of the Overlay element
3087
* to ensure that the iframe shim has a non-negative zindex.
3088
* If you require the iframe zindex to be 0 or higher, the zindex of
3089
* the Overlay element should be set to a value greater than 0, before
3090
* this method is called.
3092
* @method stackIframe
3094
stackIframe: function () {
3096
var overlayZ = Dom.getStyle(this.element, "zIndex");
3097
if (!YAHOO.lang.isUndefined(overlayZ) && !isNaN(overlayZ)) {
3098
Dom.setStyle(this.iframe, "zIndex", (overlayZ - 1));
3104
* The default event handler fired when the "iframe" property is changed.
3105
* @method configIframe
3106
* @param {String} type The CustomEvent type (usually the property name)
3107
* @param {Object[]} args The CustomEvent arguments. For configuration
3108
* handlers, args[0] will equal the newly applied value for the property.
3109
* @param {Object} obj The scope object. For configuration handlers,
3110
* this will usually equal the owner.
3112
configIframe: function (type, args, obj) {
3114
var bIFrame = args[0];
3116
function createIFrame() {
3118
var oIFrame = this.iframe,
3119
oElement = this.element,
3123
if (!m_oIFrameTemplate) {
3124
m_oIFrameTemplate = document.createElement("iframe");
3126
if (this.isSecure) {
3127
m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
3131
Set the opacity of the <iframe> to 0 so that it
3132
doesn't modify the opacity of any transparent
3133
elements that may be on top of it (like a shadow).
3136
m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
3138
Need to set the "frameBorder" property to 0
3139
supress the default <iframe> border in IE.
3140
Setting the CSS "border" property alone
3143
m_oIFrameTemplate.frameBorder = 0;
3146
m_oIFrameTemplate.style.opacity = "0";
3149
m_oIFrameTemplate.style.position = "absolute";
3150
m_oIFrameTemplate.style.border = "none";
3151
m_oIFrameTemplate.style.margin = "0";
3152
m_oIFrameTemplate.style.padding = "0";
3153
m_oIFrameTemplate.style.display = "none";
3154
m_oIFrameTemplate.tabIndex = -1;
3157
oIFrame = m_oIFrameTemplate.cloneNode(false);
3158
oParent = oElement.parentNode;
3160
var parentNode = oParent || document.body;
3162
this._addToParent(parentNode, oIFrame);
3163
this.iframe = oIFrame;
3167
Show the <iframe> before positioning it since the "setXY"
3168
method of DOM requires the element be in the document
3174
Syncronize the size and position of the <iframe> to that
3180
// Add event listeners to update the <iframe> when necessary
3181
if (!this._hasIframeEventListeners) {
3182
this.showEvent.subscribe(this.showIframe);
3183
this.hideEvent.subscribe(this.hideIframe);
3184
this.changeContentEvent.subscribe(this.syncIframe);
3186
this._hasIframeEventListeners = true;
3190
function onBeforeShow() {
3191
createIFrame.call(this);
3192
this.beforeShowEvent.unsubscribe(onBeforeShow);
3193
this._iframeDeferred = false;
3196
if (bIFrame) { // <iframe> shim is enabled
3198
if (this.cfg.getProperty("visible")) {
3199
createIFrame.call(this);
3201
if (!this._iframeDeferred) {
3202
this.beforeShowEvent.subscribe(onBeforeShow);
3203
this._iframeDeferred = true;
3207
} else { // <iframe> shim is disabled
3210
if (this._hasIframeEventListeners) {
3211
this.showEvent.unsubscribe(this.showIframe);
3212
this.hideEvent.unsubscribe(this.hideIframe);
3213
this.changeContentEvent.unsubscribe(this.syncIframe);
3215
this._hasIframeEventListeners = false;
3221
* Set's the container's XY value from DOM if not already set.
3223
* Differs from syncPosition, in that the XY value is only sync'd with DOM if
3224
* not already set. The method also refire's the XY config property event, so any
3225
* beforeMove, Move event listeners are invoked.
3227
* @method _primeXYFromDOM
3230
_primeXYFromDOM : function() {
3231
if (YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))) {
3232
// Set CFG XY based on DOM XY
3233
this.syncPosition();
3234
// Account for XY being set silently in syncPosition (no moveTo fired/called)
3235
this.cfg.refireEvent("xy");
3236
this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3241
* The default event handler fired when the "constraintoviewport"
3242
* property is changed.
3243
* @method configConstrainToViewport
3244
* @param {String} type The CustomEvent type (usually the property name)
3245
* @param {Object[]} args The CustomEvent arguments. For configuration
3246
* handlers, args[0] will equal the newly applied value for
3248
* @param {Object} obj The scope object. For configuration handlers,
3249
* this will usually equal the owner.
3251
configConstrainToViewport: function (type, args, obj) {
3255
if (! Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
3256
this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
3258
if (! Config.alreadySubscribed(this.beforeShowEvent, this._primeXYFromDOM)) {
3259
this.beforeShowEvent.subscribe(this._primeXYFromDOM);
3262
this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3263
this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
3268
* The default event handler fired when the "context" property
3271
* @method configContext
3272
* @param {String} type The CustomEvent type (usually the property name)
3273
* @param {Object[]} args The CustomEvent arguments. For configuration
3274
* handlers, args[0] will equal the newly applied value for the property.
3275
* @param {Object} obj The scope object. For configuration handlers,
3276
* this will usually equal the owner.
3278
configContext: function (type, args, obj) {
3280
var contextArgs = args[0],
3282
elementMagnetCorner,
3283
contextMagnetCorner,
3285
defTriggers = this.CONTEXT_TRIGGERS;
3289
contextEl = contextArgs[0];
3290
elementMagnetCorner = contextArgs[1];
3291
contextMagnetCorner = contextArgs[2];
3292
triggers = contextArgs[3];
3294
if (defTriggers && defTriggers.length > 0) {
3295
triggers = (triggers || []).concat(defTriggers);
3299
if (typeof contextEl == "string") {
3300
this.cfg.setProperty("context", [
3301
document.getElementById(contextEl),
3302
elementMagnetCorner,
3303
contextMagnetCorner,
3308
if (elementMagnetCorner && contextMagnetCorner) {
3309
this.align(elementMagnetCorner, contextMagnetCorner);
3312
if (this._contextTriggers) {
3313
// Unsubscribe Old Set
3314
this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
3318
// Subscribe New Set
3319
this._processTriggers(triggers, _SUBSCRIBE, this._alignOnTrigger);
3320
this._contextTriggers = triggers;
3327
* Custom Event handler for context alignment triggers. Invokes the align method
3329
* @method _alignOnTrigger
3332
* @param {String} type The event type (not used by the default implementation)
3333
* @param {Any[]} args The array of arguments for the trigger event (not used by the default implementation)
3335
_alignOnTrigger: function(type, args) {
3340
* Helper method to locate the custom event instance for the event name string
3341
* passed in. As a convenience measure, any custom events passed in are returned.
3343
* @method _findTriggerCE
3346
* @param {String|CustomEvent} t Either a CustomEvent, or event type (e.g. "windowScroll") for which a
3347
* custom event instance needs to be looked up from the Overlay._TRIGGER_MAP.
3349
_findTriggerCE : function(t) {
3351
if (t instanceof CustomEvent) {
3353
} else if (Overlay._TRIGGER_MAP[t]) {
3354
tce = Overlay._TRIGGER_MAP[t];
3360
* Utility method that subscribes or unsubscribes the given
3361
* function from the list of trigger events provided.
3363
* @method _processTriggers
3366
* @param {Array[String|CustomEvent]} triggers An array of either CustomEvents, event type strings
3367
* (e.g. "beforeShow", "windowScroll") to/from which the provided function should be
3368
* subscribed/unsubscribed respectively.
3370
* @param {String} mode Either "subscribe" or "unsubscribe", specifying whether or not
3371
* we are subscribing or unsubscribing trigger listeners
3373
* @param {Function} fn The function to be subscribed/unsubscribed to/from the trigger event.
3374
* Context is always set to the overlay instance, and no additional object argument
3375
* get passed to the subscribed function.
3377
_processTriggers : function(triggers, mode, fn) {
3380
for (var i = 0, l = triggers.length; i < l; ++i) {
3382
tce = this._findTriggerCE(t);
3384
tce[mode](fn, this, true);
3391
// END BUILT-IN PROPERTY EVENT HANDLERS //
3393
* Aligns the Overlay to its context element using the specified corner
3394
* points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT,
3397
* @param {String} elementAlign The String representing the corner of
3398
* the Overlay that should be aligned to the context element
3399
* @param {String} contextAlign The corner of the context element
3400
* that the elementAlign corner should stick to.
3402
align: function (elementAlign, contextAlign) {
3404
var contextArgs = this.cfg.getProperty("context"),
3410
function doAlign(v, h) {
3412
switch (elementAlign) {
3414
case Overlay.TOP_LEFT:
3418
case Overlay.TOP_RIGHT:
3419
me.moveTo((h - element.offsetWidth), v);
3422
case Overlay.BOTTOM_LEFT:
3423
me.moveTo(h, (v - element.offsetHeight));
3426
case Overlay.BOTTOM_RIGHT:
3427
me.moveTo((h - element.offsetWidth),
3428
(v - element.offsetHeight));
3436
context = contextArgs[0];
3437
element = this.element;
3440
if (! elementAlign) {
3441
elementAlign = contextArgs[1];
3444
if (! contextAlign) {
3445
contextAlign = contextArgs[2];
3448
if (element && context) {
3449
contextRegion = Dom.getRegion(context);
3451
switch (contextAlign) {
3453
case Overlay.TOP_LEFT:
3454
doAlign(contextRegion.top, contextRegion.left);
3457
case Overlay.TOP_RIGHT:
3458
doAlign(contextRegion.top, contextRegion.right);
3461
case Overlay.BOTTOM_LEFT:
3462
doAlign(contextRegion.bottom, contextRegion.left);
3465
case Overlay.BOTTOM_RIGHT:
3466
doAlign(contextRegion.bottom, contextRegion.right);
3477
* The default event handler executed when the moveEvent is fired, if the
3478
* "constraintoviewport" is set to true.
3479
* @method enforceConstraints
3480
* @param {String} type The CustomEvent type (usually the property name)
3481
* @param {Object[]} args The CustomEvent arguments. For configuration
3482
* handlers, args[0] will equal the newly applied value for the property.
3483
* @param {Object} obj The scope object. For configuration handlers,
3484
* this will usually equal the owner.
3486
enforceConstraints: function (type, args, obj) {
3489
var cXY = this.getConstrainedXY(pos[0], pos[1]);
3490
this.cfg.setProperty("x", cXY[0], true);
3491
this.cfg.setProperty("y", cXY[1], true);
3492
this.cfg.setProperty("xy", cXY, true);
3497
* Given x coordinate value, returns the calculated x coordinate required to
3498
* position the Overlay if it is to be constrained to the viewport, based on the
3499
* current element size, viewport dimensions and scroll values.
3501
* @param {Number} x The X coordinate value to be constrained
3502
* @return {Number} The constrained x coordinate
3504
getConstrainedX: function (x) {
3506
var oOverlay = this,
3507
oOverlayEl = oOverlay.element,
3508
nOverlayOffsetWidth = oOverlayEl.offsetWidth,
3510
nViewportOffset = Overlay.VIEWPORT_OFFSET,
3511
viewPortWidth = Dom.getViewportWidth(),
3512
scrollX = Dom.getDocumentScrollLeft(),
3514
bCanConstrain = (nOverlayOffsetWidth + nViewportOffset < viewPortWidth),
3516
aContext = this.cfg.getProperty("context"),
3526
leftConstraint = scrollX + nViewportOffset,
3527
rightConstraint = scrollX + viewPortWidth - nOverlayOffsetWidth - nViewportOffset,
3531
oOverlapPositions = {
3541
var flipHorizontal = function () {
3545
if ((oOverlay.cfg.getProperty("x") - scrollX) > nContextElX) {
3546
nNewX = (nContextElX - nOverlayOffsetWidth);
3549
nNewX = (nContextElX + nContextElWidth);
3553
oOverlay.cfg.setProperty("x", (nNewX + scrollX), true);
3562
Uses the context element's position to calculate the availble width
3563
to the right and left of it to display its corresponding Overlay.
3566
var getDisplayRegionWidth = function () {
3568
// The Overlay is to the right of the context element
3570
if ((oOverlay.cfg.getProperty("x") - scrollX) > nContextElX) {
3571
return (nRightRegionWidth - nViewportOffset);
3573
else { // The Overlay is to the left of the context element
3574
return (nLeftRegionWidth - nViewportOffset);
3581
Positions the Overlay to the left or right of the context element so that it remains
3582
inside the viewport.
3585
var setHorizontalPosition = function () {
3587
var nDisplayRegionWidth = getDisplayRegionWidth(),
3590
if (nOverlayOffsetWidth > nDisplayRegionWidth) {
3595
All possible positions and values have been
3596
tried, but none were successful, so fall back
3597
to the original size and position.
3609
fnReturnVal = setHorizontalPosition();
3619
// Determine if the current value for the Overlay's "x" configuration property will
3620
// result in the Overlay being positioned outside the boundaries of the viewport
3622
if (x < leftConstraint || x > rightConstraint) {
3624
// The current value for the Overlay's "x" configuration property WILL
3625
// result in the Overlay being positioned outside the boundaries of the viewport
3627
if (bCanConstrain) {
3629
// If the "preventcontextoverlap" configuration property is set to "true",
3630
// try to flip the Overlay to both keep it inside the boundaries of the
3631
// viewport AND from overlaping its context element.
3633
if (this.cfg.getProperty("preventcontextoverlap") && aContext &&
3634
oOverlapPositions[(aContext[1] + aContext[2])]) {
3636
oContextEl = aContext[0];
3637
nContextElX = Dom.getX(oContextEl) - scrollX;
3638
nContextElWidth = oContextEl.offsetWidth;
3639
nLeftRegionWidth = nContextElX;
3640
nRightRegionWidth = (viewPortWidth - (nContextElX + nContextElWidth));
3642
setHorizontalPosition();
3644
xNew = this.cfg.getProperty("x");
3649
if (x < leftConstraint) {
3650
xNew = leftConstraint;
3651
} else if (x > rightConstraint) {
3652
xNew = rightConstraint;
3658
// The "x" configuration property cannot be set to a value that will keep
3659
// entire Overlay inside the boundary of the viewport. Therefore, set
3660
// the "x" configuration property to scrollY to keep as much of the
3661
// Overlay inside the viewport as possible.
3662
xNew = nViewportOffset + scrollX;
3673
* Given y coordinate value, returns the calculated y coordinate required to
3674
* position the Overlay if it is to be constrained to the viewport, based on the
3675
* current element size, viewport dimensions and scroll values.
3677
* @param {Number} y The Y coordinate value to be constrained
3678
* @return {Number} The constrained y coordinate
3680
getConstrainedY: function (y) {
3682
var oOverlay = this,
3683
oOverlayEl = oOverlay.element,
3684
nOverlayOffsetHeight = oOverlayEl.offsetHeight,
3686
nViewportOffset = Overlay.VIEWPORT_OFFSET,
3687
viewPortHeight = Dom.getViewportHeight(),
3688
scrollY = Dom.getDocumentScrollTop(),
3690
bCanConstrain = (nOverlayOffsetHeight + nViewportOffset < viewPortHeight),
3692
aContext = this.cfg.getProperty("context"),
3700
nBottomRegionHeight,
3702
topConstraint = scrollY + nViewportOffset,
3703
bottomConstraint = scrollY + viewPortHeight - nOverlayOffsetHeight - nViewportOffset,
3707
oOverlapPositions = {
3715
var flipVertical = function () {
3719
// The Overlay is below the context element, flip it above
3720
if ((oOverlay.cfg.getProperty("y") - scrollY) > nContextElY) {
3721
nNewY = (nContextElY - nOverlayOffsetHeight);
3723
else { // The Overlay is above the context element, flip it below
3724
nNewY = (nContextElY + nContextElHeight);
3727
oOverlay.cfg.setProperty("y", (nNewY + scrollY), true);
3735
Uses the context element's position to calculate the availble height
3736
above and below it to display its corresponding Overlay.
3739
var getDisplayRegionHeight = function () {
3741
// The Overlay is below the context element
3742
if ((oOverlay.cfg.getProperty("y") - scrollY) > nContextElY) {
3743
return (nBottomRegionHeight - nViewportOffset);
3745
else { // The Overlay is above the context element
3746
return (nTopRegionHeight - nViewportOffset);
3753
Trys to place the Overlay in the best possible position (either above or
3754
below its corresponding context element).
3757
var setVerticalPosition = function () {
3759
var nDisplayRegionHeight = getDisplayRegionHeight(),
3763
if (nOverlayOffsetHeight > nDisplayRegionHeight) {
3768
All possible positions and values for the
3769
"maxheight" configuration property have been
3770
tried, but none were successful, so fall back
3771
to the original size and position.
3783
fnReturnVal = setVerticalPosition();
3794
// Determine if the current value for the Overlay's "y" configuration property will
3795
// result in the Overlay being positioned outside the boundaries of the viewport
3797
if (y < topConstraint || y > bottomConstraint) {
3799
// The current value for the Overlay's "y" configuration property WILL
3800
// result in the Overlay being positioned outside the boundaries of the viewport
3802
if (bCanConstrain) {
3804
// If the "preventcontextoverlap" configuration property is set to "true",
3805
// try to flip the Overlay to both keep it inside the boundaries of the
3806
// viewport AND from overlaping its context element.
3808
if (this.cfg.getProperty("preventcontextoverlap") && aContext &&
3809
oOverlapPositions[(aContext[1] + aContext[2])]) {
3811
oContextEl = aContext[0];
3812
nContextElHeight = oContextEl.offsetHeight;
3813
nContextElY = (Dom.getY(oContextEl) - scrollY);
3815
nTopRegionHeight = nContextElY;
3816
nBottomRegionHeight = (viewPortHeight - (nContextElY + nContextElHeight));
3818
setVerticalPosition();
3820
yNew = oOverlay.cfg.getProperty("y");
3825
if (y < topConstraint) {
3826
yNew = topConstraint;
3827
} else if (y > bottomConstraint) {
3828
yNew = bottomConstraint;
3836
// The "y" configuration property cannot be set to a value that will keep
3837
// entire Overlay inside the boundary of the viewport. Therefore, set
3838
// the "y" configuration property to scrollY to keep as much of the
3839
// Overlay inside the viewport as possible.
3841
yNew = nViewportOffset + scrollY;
3851
* Given x, y coordinate values, returns the calculated coordinates required to
3852
* position the Overlay if it is to be constrained to the viewport, based on the
3853
* current element size, viewport dimensions and scroll values.
3855
* @param {Number} x The X coordinate value to be constrained
3856
* @param {Number} y The Y coordinate value to be constrained
3857
* @return {Array} The constrained x and y coordinates at index 0 and 1 respectively;
3859
getConstrainedXY: function(x, y) {
3860
return [this.getConstrainedX(x), this.getConstrainedY(y)];
3864
* Centers the container in the viewport.
3867
center: function () {
3869
var nViewportOffset = Overlay.VIEWPORT_OFFSET,
3870
elementWidth = this.element.offsetWidth,
3871
elementHeight = this.element.offsetHeight,
3872
viewPortWidth = Dom.getViewportWidth(),
3873
viewPortHeight = Dom.getViewportHeight(),
3877
if (elementWidth < viewPortWidth) {
3878
x = (viewPortWidth / 2) - (elementWidth / 2) + Dom.getDocumentScrollLeft();
3880
x = nViewportOffset + Dom.getDocumentScrollLeft();
3883
if (elementHeight < viewPortHeight) {
3884
y = (viewPortHeight / 2) - (elementHeight / 2) + Dom.getDocumentScrollTop();
3886
y = nViewportOffset + Dom.getDocumentScrollTop();
3889
this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
3890
this.cfg.refireEvent("iframe");
3893
this.forceContainerRedraw();
3898
* Synchronizes the Panel's "xy", "x", and "y" properties with the
3899
* Panel's position in the DOM. This is primarily used to update
3900
* position information during drag & drop.
3901
* @method syncPosition
3903
syncPosition: function () {
3905
var pos = Dom.getXY(this.element);
3907
this.cfg.setProperty("x", pos[0], true);
3908
this.cfg.setProperty("y", pos[1], true);
3909
this.cfg.setProperty("xy", pos, true);
3914
* Event handler fired when the resize monitor element is resized.
3915
* @method onDomResize
3916
* @param {DOMEvent} e The resize DOM event
3917
* @param {Object} obj The scope object
3919
onDomResize: function (e, obj) {
3923
Overlay.superclass.onDomResize.call(this, e, obj);
3925
setTimeout(function () {
3927
me.cfg.refireEvent("iframe");
3928
me.cfg.refireEvent("context");
3933
* Determines the content box height of the given element (height of the element, without padding or borders) in pixels.
3935
* @method _getComputedHeight
3937
* @param {HTMLElement} el The element for which the content height needs to be determined
3938
* @return {Number} The content box height of the given element, or null if it could not be determined.
3940
_getComputedHeight : (function() {
3942
if (document.defaultView && document.defaultView.getComputedStyle) {
3943
return function(el) {
3945
if (el.ownerDocument && el.ownerDocument.defaultView) {
3946
var computed = el.ownerDocument.defaultView.getComputedStyle(el, '');
3948
height = parseInt(computed.height, 10);
3951
return (Lang.isNumber(height)) ? height : null;
3954
return function(el) {
3956
if (el.style.pixelHeight) {
3957
height = el.style.pixelHeight;
3959
return (Lang.isNumber(height)) ? height : null;
3965
* autofillheight validator. Verifies that the autofill value is either null
3966
* or one of the strings : "body", "header" or "footer".
3968
* @method _validateAutoFillHeight
3970
* @param {String} val
3971
* @return true, if valid, false otherwise
3973
_validateAutoFillHeight : function(val) {
3974
return (!val) || (Lang.isString(val) && Overlay.STD_MOD_RE.test(val));
3978
* The default custom event handler executed when the overlay's height is changed,
3979
* if the autofillheight property has been set.
3981
* @method _autoFillOnHeightChange
3983
* @param {String} type The event type
3984
* @param {Array} args The array of arguments passed to event subscribers
3985
* @param {HTMLElement} el The header, body or footer element which is to be resized to fill
3986
* out the containers height
3988
_autoFillOnHeightChange : function(type, args, el) {
3989
var height = this.cfg.getProperty("height");
3990
if ((height && height !== "auto") || (height === 0)) {
3991
this.fillHeight(el);
3996
* Returns the sub-pixel height of the el, using getBoundingClientRect, if available,
3997
* otherwise returns the offsetHeight
3998
* @method _getPreciseHeight
4000
* @param {HTMLElement} el
4001
* @return {Float} The sub-pixel height if supported by the browser, else the rounded height.
4003
_getPreciseHeight : function(el) {
4004
var height = el.offsetHeight;
4006
if (el.getBoundingClientRect) {
4007
var rect = el.getBoundingClientRect();
4008
height = rect.bottom - rect.top;
4016
* Sets the height on the provided header, body or footer element to
4017
* fill out the height of the container. It determines the height of the
4018
* containers content box, based on it's configured height value, and
4019
* sets the height of the autofillheight element to fill out any
4020
* space remaining after the other standard module element heights
4021
* have been accounted for.
4023
* <p><strong>NOTE:</strong> This method is not designed to work if an explicit
4024
* height has not been set on the container, since for an "auto" height container,
4025
* the heights of the header/body/footer will drive the height of the container.</p>
4027
* @method fillHeight
4028
* @param {HTMLElement} el The element which should be resized to fill out the height
4029
* of the container element.
4031
fillHeight : function(el) {
4033
var container = this.innerElement || this.element,
4034
containerEls = [this.header, this.body, this.footer],
4041
for (var i = 0, l = containerEls.length; i < l; i++) {
4042
containerEl = containerEls[i];
4044
if (el !== containerEl) {
4045
filled += this._getPreciseHeight(containerEl);
4054
if (UA.ie || UA.opera) {
4055
// Need to set height to 0, to allow height to be reduced
4056
Dom.setStyle(el, 'height', 0 + 'px');
4059
total = this._getComputedHeight(container);
4061
// Fallback, if we can't get computed value for content height
4062
if (total === null) {
4063
Dom.addClass(container, "yui-override-padding");
4064
total = container.clientHeight; // Content, No Border, 0 Padding (set by yui-override-padding)
4065
Dom.removeClass(container, "yui-override-padding");
4068
remaining = Math.max(total - filled, 0);
4070
Dom.setStyle(el, "height", remaining + "px");
4072
// Re-adjust height if required, to account for el padding and border
4073
if (el.offsetHeight != remaining) {
4074
remaining = Math.max(remaining - (el.offsetHeight - remaining), 0);
4076
Dom.setStyle(el, "height", remaining + "px");
4082
* Places the Overlay on top of all other instances of
4083
* YAHOO.widget.Overlay.
4084
* @method bringToTop
4086
bringToTop: function () {
4089
oElement = this.element;
4091
function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
4093
var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
4094
sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
4096
nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 0 : parseInt(sZIndex1, 10),
4097
nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 0 : parseInt(sZIndex2, 10);
4099
if (nZIndex1 > nZIndex2) {
4101
} else if (nZIndex1 < nZIndex2) {
4108
function isOverlayElement(p_oElement) {
4110
var isOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
4111
Panel = YAHOO.widget.Panel;
4113
if (isOverlay && !Dom.isAncestor(oElement, p_oElement)) {
4114
if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
4115
aOverlays[aOverlays.length] = p_oElement.parentNode;
4117
aOverlays[aOverlays.length] = p_oElement;
4122
Dom.getElementsBy(isOverlayElement, "DIV", document.body);
4124
aOverlays.sort(compareZIndexDesc);
4126
var oTopOverlay = aOverlays[0],
4130
nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
4132
if (!isNaN(nTopZIndex)) {
4133
var bRequiresBump = false;
4135
if (oTopOverlay != oElement) {
4136
bRequiresBump = true;
4137
} else if (aOverlays.length > 1) {
4138
var nNextZIndex = Dom.getStyle(aOverlays[1], "zIndex");
4139
// Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4140
if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4141
bRequiresBump = true;
4144
if (bRequiresBump) {
4145
this.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4152
* Removes the Overlay element from the DOM and sets all child
4156
destroy: function () {
4159
this.iframe.parentNode.removeChild(this.iframe);
4164
Overlay.windowResizeEvent.unsubscribe(
4165
this.doCenterOnDOMEvent, this);
4167
Overlay.windowScrollEvent.unsubscribe(
4168
this.doCenterOnDOMEvent, this);
4170
Module.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);
4172
Overlay.superclass.destroy.call(this);
4176
* Can be used to force the container to repaint/redraw it's contents.
4178
* By default applies and then removes a 1px bottom margin through the
4179
* application/removal of a "yui-force-redraw" class.
4182
* It is currently used by Overlay to force a repaint for webkit
4183
* browsers, when centering.
4185
* @method forceContainerRedraw
4187
forceContainerRedraw : function() {
4189
Dom.addClass(c.element, "yui-force-redraw");
4190
setTimeout(function() {
4191
Dom.removeClass(c.element, "yui-force-redraw");
4196
* Returns a String representation of the object.
4198
* @return {String} The string representation of the Overlay.
4200
toString: function () {
4201
return "Overlay " + this.id;
4210
* OverlayManager is used for maintaining the focus status of
4211
* multiple Overlays.
4212
* @namespace YAHOO.widget
4213
* @namespace YAHOO.widget
4214
* @class OverlayManager
4216
* @param {Array} overlays Optional. A collection of Overlays to register
4218
* @param {Object} userConfig The object literal representing the user
4219
* configuration of the OverlayManager
4221
YAHOO.widget.OverlayManager = function (userConfig) {
4222
this.init(userConfig);
4225
var Overlay = YAHOO.widget.Overlay,
4226
Event = YAHOO.util.Event,
4227
Dom = YAHOO.util.Dom,
4228
Config = YAHOO.util.Config,
4229
CustomEvent = YAHOO.util.CustomEvent,
4230
OverlayManager = YAHOO.widget.OverlayManager;
4233
* The CSS class representing a focused Overlay
4234
* @property OverlayManager.CSS_FOCUSED
4239
OverlayManager.CSS_FOCUSED = "focused";
4241
OverlayManager.prototype = {
4244
* The class's constructor function
4245
* @property contructor
4248
constructor: OverlayManager,
4251
* The array of Overlays that are currently registered
4252
* @property overlays
4253
* @type YAHOO.widget.Overlay[]
4258
* Initializes the default configuration of the OverlayManager
4259
* @method initDefaultConfig
4261
initDefaultConfig: function () {
4263
* The collection of registered Overlays in use by
4264
* the OverlayManager
4266
* @type YAHOO.widget.Overlay[]
4269
this.cfg.addProperty("overlays", { suppressEvent: true } );
4272
* The default DOM event that should be used to focus an Overlay
4273
* @config focusevent
4275
* @default "mousedown"
4277
this.cfg.addProperty("focusevent", { value: "mousedown" } );
4281
* Initializes the OverlayManager
4283
* @param {Overlay[]} overlays Optional. A collection of Overlays to
4284
* register with the manager.
4285
* @param {Object} userConfig The object literal representing the user
4286
* configuration of the OverlayManager
4288
init: function (userConfig) {
4291
* The OverlayManager's Config object used for monitoring
4292
* configuration properties.
4296
this.cfg = new Config(this);
4298
this.initDefaultConfig();
4301
this.cfg.applyConfig(userConfig, true);
4303
this.cfg.fireQueue();
4306
* The currently activated Overlay
4307
* @property activeOverlay
4309
* @type YAHOO.widget.Overlay
4311
var activeOverlay = null;
4314
* Returns the currently focused Overlay
4316
* @return {Overlay} The currently focused Overlay
4318
this.getActive = function () {
4319
return activeOverlay;
4323
* Focuses the specified Overlay
4325
* @param {Overlay} overlay The Overlay to focus
4326
* @param {String} overlay The id of the Overlay to focus
4328
this.focus = function (overlay) {
4329
var o = this.find(overlay);
4336
* Removes the specified Overlay from the manager
4338
* @param {Overlay} overlay The Overlay to remove
4339
* @param {String} overlay The id of the Overlay to remove
4341
this.remove = function (overlay) {
4343
var o = this.find(overlay),
4347
if (activeOverlay == o) {
4348
activeOverlay = null;
4351
var bDestroyed = (o.element === null && o.cfg === null) ? true : false;
4354
// Set it's zindex so that it's sorted to the end.
4355
originalZ = Dom.getStyle(o.element, "zIndex");
4356
o.cfg.setProperty("zIndex", -1000, true);
4359
this.overlays.sort(this.compareZIndexDesc);
4360
this.overlays = this.overlays.slice(0, (this.overlays.length - 1));
4362
o.hideEvent.unsubscribe(o.blur);
4363
o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
4364
o.focusEvent.unsubscribe(this._onOverlayFocusHandler, o);
4365
o.blurEvent.unsubscribe(this._onOverlayBlurHandler, o);
4368
Event.removeListener(o.element, this.cfg.getProperty("focusevent"), this._onOverlayElementFocus);
4369
o.cfg.setProperty("zIndex", originalZ, true);
4370
o.cfg.setProperty("manager", null);
4373
/* _managed Flag for custom or existing. Don't want to remove existing */
4374
if (o.focusEvent._managed) { o.focusEvent = null; }
4375
if (o.blurEvent._managed) { o.blurEvent = null; }
4377
if (o.focus._managed) { o.focus = null; }
4378
if (o.blur._managed) { o.blur = null; }
4383
* Removes focus from all registered Overlays in the manager
4386
this.blurAll = function () {
4388
var nOverlays = this.overlays.length,
4391
if (nOverlays > 0) {
4394
this.overlays[i].blur();
4401
* Updates the state of the OverlayManager and overlay, as a result of the overlay
4404
* @method _manageBlur
4405
* @param {Overlay} overlay The overlay instance which got blurred.
4408
this._manageBlur = function (overlay) {
4409
var changed = false;
4410
if (activeOverlay == overlay) {
4411
Dom.removeClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4412
activeOverlay = null;
4419
* Updates the state of the OverlayManager and overlay, as a result of the overlay
4422
* @method _manageFocus
4423
* @param {Overlay} overlay The overlay instance which got focus.
4426
this._manageFocus = function(overlay) {
4427
var changed = false;
4428
if (activeOverlay != overlay) {
4429
if (activeOverlay) {
4430
activeOverlay.blur();
4432
activeOverlay = overlay;
4433
this.bringToTop(activeOverlay);
4434
Dom.addClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4440
var overlays = this.cfg.getProperty("overlays");
4442
if (! this.overlays) {
4447
this.register(overlays);
4448
this.overlays.sort(this.compareZIndexDesc);
4453
* @method _onOverlayElementFocus
4454
* @description Event handler for the DOM event that is used to focus
4455
* the Overlay instance as specified by the "focusevent"
4456
* configuration property.
4458
* @param {Event} p_oEvent Object representing the DOM event
4459
* object passed back by the event utility (Event).
4461
_onOverlayElementFocus: function (p_oEvent) {
4463
var oTarget = Event.getTarget(p_oEvent),
4464
oClose = this.close;
4466
if (oClose && (oTarget == oClose || Dom.isAncestor(oClose, oTarget))) {
4474
* @method _onOverlayDestroy
4475
* @description "destroy" event handler for the Overlay.
4477
* @param {String} p_sType String representing the name of the event
4479
* @param {Array} p_aArgs Array of arguments sent when the event
4481
* @param {Overlay} p_oOverlay Object representing the overlay that
4484
_onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
4485
this.remove(p_oOverlay);
4489
* @method _onOverlayFocusHandler
4491
* focusEvent Handler, used to delegate to _manageFocus with the
4492
* correct arguments.
4495
* @param {String} p_sType String representing the name of the event
4497
* @param {Array} p_aArgs Array of arguments sent when the event
4499
* @param {Overlay} p_oOverlay Object representing the overlay that
4502
_onOverlayFocusHandler: function(p_sType, p_aArgs, p_oOverlay) {
4503
this._manageFocus(p_oOverlay);
4507
* @method _onOverlayBlurHandler
4509
* blurEvent Handler, used to delegate to _manageBlur with the
4510
* correct arguments.
4513
* @param {String} p_sType String representing the name of the event
4515
* @param {Array} p_aArgs Array of arguments sent when the event
4517
* @param {Overlay} p_oOverlay Object representing the overlay that
4520
_onOverlayBlurHandler: function(p_sType, p_aArgs, p_oOverlay) {
4521
this._manageBlur(p_oOverlay);
4525
* Subscribes to the Overlay based instance focusEvent, to allow the OverlayManager to
4526
* monitor focus state.
4528
* If the instance already has a focusEvent (e.g. Menu), OverlayManager will subscribe
4529
* to the existing focusEvent, however if a focusEvent or focus method does not exist
4530
* on the instance, the _bindFocus method will add them, and the focus method will
4531
* update the OverlayManager's state directly.
4533
* @method _bindFocus
4534
* @param {Overlay} overlay The overlay for which focus needs to be managed
4537
_bindFocus : function(overlay) {
4540
if (!overlay.focusEvent) {
4541
overlay.focusEvent = overlay.createEvent("focus");
4542
overlay.focusEvent.signature = CustomEvent.LIST;
4543
overlay.focusEvent._managed = true;
4545
overlay.focusEvent.subscribe(mgr._onOverlayFocusHandler, overlay, mgr);
4548
if (!overlay.focus) {
4549
Event.on(overlay.element, mgr.cfg.getProperty("focusevent"), mgr._onOverlayElementFocus, null, overlay);
4550
overlay.focus = function () {
4551
if (mgr._manageFocus(this)) {
4553
if (this.cfg.getProperty("visible") && this.focusFirst) {
4556
this.focusEvent.fire();
4559
overlay.focus._managed = true;
4564
* Subscribes to the Overlay based instance's blurEvent to allow the OverlayManager to
4565
* monitor blur state.
4567
* If the instance already has a blurEvent (e.g. Menu), OverlayManager will subscribe
4568
* to the existing blurEvent, however if a blurEvent or blur method does not exist
4569
* on the instance, the _bindBlur method will add them, and the blur method
4570
* update the OverlayManager's state directly.
4573
* @param {Overlay} overlay The overlay for which blur needs to be managed
4576
_bindBlur : function(overlay) {
4579
if (!overlay.blurEvent) {
4580
overlay.blurEvent = overlay.createEvent("blur");
4581
overlay.blurEvent.signature = CustomEvent.LIST;
4582
overlay.focusEvent._managed = true;
4584
overlay.blurEvent.subscribe(mgr._onOverlayBlurHandler, overlay, mgr);
4587
if (!overlay.blur) {
4588
overlay.blur = function () {
4589
if (mgr._manageBlur(this)) {
4590
this.blurEvent.fire();
4593
overlay.blur._managed = true;
4596
overlay.hideEvent.subscribe(overlay.blur);
4600
* Subscribes to the Overlay based instance's destroyEvent, to allow the Overlay
4601
* to be removed for the OverlayManager when destroyed.
4603
* @method _bindDestroy
4604
* @param {Overlay} overlay The overlay instance being managed
4607
_bindDestroy : function(overlay) {
4609
overlay.destroyEvent.subscribe(mgr._onOverlayDestroy, overlay, mgr);
4613
* Ensures the zIndex configuration property on the managed overlay based instance
4614
* is set to the computed zIndex value from the DOM (with "auto" translating to 0).
4616
* @method _syncZIndex
4617
* @param {Overlay} overlay The overlay instance being managed
4620
_syncZIndex : function(overlay) {
4621
var zIndex = Dom.getStyle(overlay.element, "zIndex");
4622
if (!isNaN(zIndex)) {
4623
overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
4625
overlay.cfg.setProperty("zIndex", 0);
4630
* Registers an Overlay or an array of Overlays with the manager. Upon
4631
* registration, the Overlay receives functions for focus and blur,
4632
* along with CustomEvents for each.
4635
* @param {Overlay} overlay An Overlay to register with the manager.
4636
* @param {Overlay[]} overlay An array of Overlays to register with
4638
* @return {boolean} true if any Overlays are registered.
4640
register: function (overlay) {
4642
var registered = false,
4646
if (overlay instanceof Overlay) {
4648
overlay.cfg.addProperty("manager", { value: this } );
4650
this._bindFocus(overlay);
4651
this._bindBlur(overlay);
4652
this._bindDestroy(overlay);
4653
this._syncZIndex(overlay);
4655
this.overlays.push(overlay);
4656
this.bringToTop(overlay);
4660
} else if (overlay instanceof Array) {
4662
for (i = 0, n = overlay.length; i < n; i++) {
4663
registered = this.register(overlay[i]) || registered;
4672
* Places the specified Overlay instance on top of all other
4673
* Overlay instances.
4674
* @method bringToTop
4675
* @param {YAHOO.widget.Overlay} p_oOverlay Object representing an
4677
* @param {String} p_oOverlay String representing the id of an
4680
bringToTop: function (p_oOverlay) {
4682
var oOverlay = this.find(p_oOverlay),
4689
aOverlays = this.overlays;
4690
aOverlays.sort(this.compareZIndexDesc);
4692
oTopOverlay = aOverlays[0];
4695
nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
4697
if (!isNaN(nTopZIndex)) {
4699
var bRequiresBump = false;
4701
if (oTopOverlay !== oOverlay) {
4702
bRequiresBump = true;
4703
} else if (aOverlays.length > 1) {
4704
var nNextZIndex = Dom.getStyle(aOverlays[1].element, "zIndex");
4705
// Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4706
if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4707
bRequiresBump = true;
4711
if (bRequiresBump) {
4712
oOverlay.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4715
aOverlays.sort(this.compareZIndexDesc);
4721
* Attempts to locate an Overlay by instance or ID.
4723
* @param {Overlay} overlay An Overlay to locate within the manager
4724
* @param {String} overlay An Overlay id to locate within the manager
4725
* @return {Overlay} The requested Overlay, if found, or null if it
4726
* cannot be located.
4728
find: function (overlay) {
4730
var isInstance = overlay instanceof Overlay,
4731
overlays = this.overlays,
4732
n = overlays.length,
4737
if (isInstance || typeof overlay == "string") {
4738
for (i = n-1; i >= 0; i--) {
4740
if ((isInstance && (o === overlay)) || (o.id == overlay)) {
4751
* Used for sorting the manager's Overlays by z-index.
4752
* @method compareZIndexDesc
4754
* @return {Number} 0, 1, or -1, depending on where the Overlay should
4755
* fall in the stacking order.
4757
compareZIndexDesc: function (o1, o2) {
4759
var zIndex1 = (o1.cfg) ? o1.cfg.getProperty("zIndex") : null, // Sort invalid (destroyed)
4760
zIndex2 = (o2.cfg) ? o2.cfg.getProperty("zIndex") : null; // objects at bottom.
4762
if (zIndex1 === null && zIndex2 === null) {
4764
} else if (zIndex1 === null){
4766
} else if (zIndex2 === null) {
4768
} else if (zIndex1 > zIndex2) {
4770
} else if (zIndex1 < zIndex2) {
4778
* Shows all Overlays in the manager.
4781
showAll: function () {
4782
var overlays = this.overlays,
4783
n = overlays.length,
4786
for (i = n - 1; i >= 0; i--) {
4792
* Hides all Overlays in the manager.
4795
hideAll: function () {
4796
var overlays = this.overlays,
4797
n = overlays.length,
4800
for (i = n - 1; i >= 0; i--) {
4806
* Returns a string representation of the object.
4808
* @return {String} The string representation of the OverlayManager
4810
toString: function () {
4811
return "OverlayManager";
4819
* ContainerEffect encapsulates animation transitions that are executed when
4820
* an Overlay is shown or hidden.
4821
* @namespace YAHOO.widget
4822
* @class ContainerEffect
4824
* @param {YAHOO.widget.Overlay} overlay The Overlay that the animation
4825
* should be associated with
4826
* @param {Object} attrIn The object literal representing the animation
4827
* arguments to be used for the animate-in transition. The arguments for
4828
* this literal are: attributes(object, see YAHOO.util.Anim for description),
4829
* duration(Number), and method(i.e. Easing.easeIn).
4830
* @param {Object} attrOut The object literal representing the animation
4831
* arguments to be used for the animate-out transition. The arguments for
4832
* this literal are: attributes(object, see YAHOO.util.Anim for description),
4833
* duration(Number), and method(i.e. Easing.easeIn).
4834
* @param {HTMLElement} targetElement Optional. The target element that
4835
* should be animated during the transition. Defaults to overlay.element.
4836
* @param {class} Optional. The animation class to instantiate. Defaults to
4837
* YAHOO.util.Anim. Other options include YAHOO.util.Motion.
4839
YAHOO.widget.ContainerEffect = function (overlay, attrIn, attrOut, targetElement, animClass) {
4842
animClass = YAHOO.util.Anim;
4846
* The overlay to animate
4848
* @type YAHOO.widget.Overlay
4850
this.overlay = overlay;
4853
* The animation attributes to use when transitioning into view
4857
this.attrIn = attrIn;
4860
* The animation attributes to use when transitioning out of view
4864
this.attrOut = attrOut;
4867
* The target element to be animated
4868
* @property targetElement
4871
this.targetElement = targetElement || overlay.element;
4874
* The animation class to use for animating the overlay
4875
* @property animClass
4878
this.animClass = animClass;
4883
var Dom = YAHOO.util.Dom,
4884
CustomEvent = YAHOO.util.CustomEvent,
4885
ContainerEffect = YAHOO.widget.ContainerEffect;
4889
* A pre-configured ContainerEffect instance that can be used for fading
4890
* an overlay in and out.
4893
* @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
4894
* @param {Number} dur The duration of the animation
4895
* @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
4897
ContainerEffect.FADE = function (overlay, dur) {
4899
var Easing = YAHOO.util.Easing,
4901
attributes: {opacity:{from:0, to:1}},
4903
method: Easing.easeIn
4906
attributes: {opacity:{to:0}},
4908
method: Easing.easeOut
4910
fade = new ContainerEffect(overlay, fin, fout, overlay.element);
4912
fade.handleUnderlayStart = function() {
4913
var underlay = this.overlay.underlay;
4914
if (underlay && YAHOO.env.ua.ie) {
4915
var hasFilters = (underlay.filters && underlay.filters.length > 0);
4917
Dom.addClass(overlay.element, "yui-effect-fade");
4922
fade.handleUnderlayComplete = function() {
4923
var underlay = this.overlay.underlay;
4924
if (underlay && YAHOO.env.ua.ie) {
4925
Dom.removeClass(overlay.element, "yui-effect-fade");
4929
fade.handleStartAnimateIn = function (type, args, obj) {
4930
Dom.addClass(obj.overlay.element, "hide-select");
4932
if (!obj.overlay.underlay) {
4933
obj.overlay.cfg.refireEvent("underlay");
4936
obj.handleUnderlayStart();
4938
obj.overlay._setDomVisibility(true);
4939
Dom.setStyle(obj.overlay.element, "opacity", 0);
4942
fade.handleCompleteAnimateIn = function (type,args,obj) {
4943
Dom.removeClass(obj.overlay.element, "hide-select");
4945
if (obj.overlay.element.style.filter) {
4946
obj.overlay.element.style.filter = null;
4949
obj.handleUnderlayComplete();
4951
obj.overlay.cfg.refireEvent("iframe");
4952
obj.animateInCompleteEvent.fire();
4955
fade.handleStartAnimateOut = function (type, args, obj) {
4956
Dom.addClass(obj.overlay.element, "hide-select");
4957
obj.handleUnderlayStart();
4960
fade.handleCompleteAnimateOut = function (type, args, obj) {
4961
Dom.removeClass(obj.overlay.element, "hide-select");
4962
if (obj.overlay.element.style.filter) {
4963
obj.overlay.element.style.filter = null;
4965
obj.overlay._setDomVisibility(false);
4966
Dom.setStyle(obj.overlay.element, "opacity", 1);
4968
obj.handleUnderlayComplete();
4970
obj.overlay.cfg.refireEvent("iframe");
4971
obj.animateOutCompleteEvent.fire();
4980
* A pre-configured ContainerEffect instance that can be used for sliding an
4981
* overlay in and out.
4984
* @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
4985
* @param {Number} dur The duration of the animation
4986
* @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
4988
ContainerEffect.SLIDE = function (overlay, dur) {
4989
var Easing = YAHOO.util.Easing,
4991
x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
4992
y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
4993
clientWidth = Dom.getClientWidth(),
4994
offsetWidth = overlay.element.offsetWidth,
4997
attributes: { points: { to: [x, y] } },
4999
method: Easing.easeIn
5003
attributes: { points: { to: [(clientWidth + 25), y] } },
5005
method: Easing.easeOut
5008
slide = new ContainerEffect(overlay, sin, sout, overlay.element, YAHOO.util.Motion);
5010
slide.handleStartAnimateIn = function (type,args,obj) {
5011
obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
5012
obj.overlay.element.style.top = y + "px";
5015
slide.handleTweenAnimateIn = function (type, args, obj) {
5017
var pos = Dom.getXY(obj.overlay.element),
5021
if (Dom.getStyle(obj.overlay.element, "visibility") ==
5022
"hidden" && currentX < x) {
5024
obj.overlay._setDomVisibility(true);
5028
obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
5029
obj.overlay.cfg.refireEvent("iframe");
5032
slide.handleCompleteAnimateIn = function (type, args, obj) {
5033
obj.overlay.cfg.setProperty("xy", [x, y], true);
5036
obj.overlay.cfg.refireEvent("iframe");
5037
obj.animateInCompleteEvent.fire();
5040
slide.handleStartAnimateOut = function (type, args, obj) {
5042
var vw = Dom.getViewportWidth(),
5043
pos = Dom.getXY(obj.overlay.element),
5046
obj.animOut.attributes.points.to = [(vw + 25), yso];
5049
slide.handleTweenAnimateOut = function (type, args, obj) {
5051
var pos = Dom.getXY(obj.overlay.element),
5055
obj.overlay.cfg.setProperty("xy", [xto, yto], true);
5056
obj.overlay.cfg.refireEvent("iframe");
5059
slide.handleCompleteAnimateOut = function (type, args, obj) {
5060
obj.overlay._setDomVisibility(false);
5062
obj.overlay.cfg.setProperty("xy", [x, y]);
5063
obj.animateOutCompleteEvent.fire();
5070
ContainerEffect.prototype = {
5073
* Initializes the animation classes and events.
5078
this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
5079
this.beforeAnimateInEvent.signature = CustomEvent.LIST;
5081
this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
5082
this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
5084
this.animateInCompleteEvent = this.createEvent("animateInComplete");
5085
this.animateInCompleteEvent.signature = CustomEvent.LIST;
5087
this.animateOutCompleteEvent =
5088
this.createEvent("animateOutComplete");
5089
this.animateOutCompleteEvent.signature = CustomEvent.LIST;
5091
this.animIn = new this.animClass(this.targetElement,
5092
this.attrIn.attributes, this.attrIn.duration,
5093
this.attrIn.method);
5095
this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
5096
this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
5098
this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn,
5101
this.animOut = new this.animClass(this.targetElement,
5102
this.attrOut.attributes, this.attrOut.duration,
5103
this.attrOut.method);
5105
this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
5106
this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
5107
this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut,
5113
* Triggers the in-animation.
5116
animateIn: function () {
5117
this.beforeAnimateInEvent.fire();
5118
this.animIn.animate();
5122
* Triggers the out-animation.
5123
* @method animateOut
5125
animateOut: function () {
5126
this.beforeAnimateOutEvent.fire();
5127
this.animOut.animate();
5131
* The default onStart handler for the in-animation.
5132
* @method handleStartAnimateIn
5133
* @param {String} type The CustomEvent type
5134
* @param {Object[]} args The CustomEvent arguments
5135
* @param {Object} obj The scope object
5137
handleStartAnimateIn: function (type, args, obj) { },
5140
* The default onTween handler for the in-animation.
5141
* @method handleTweenAnimateIn
5142
* @param {String} type The CustomEvent type
5143
* @param {Object[]} args The CustomEvent arguments
5144
* @param {Object} obj The scope object
5146
handleTweenAnimateIn: function (type, args, obj) { },
5149
* The default onComplete handler for the in-animation.
5150
* @method handleCompleteAnimateIn
5151
* @param {String} type The CustomEvent type
5152
* @param {Object[]} args The CustomEvent arguments
5153
* @param {Object} obj The scope object
5155
handleCompleteAnimateIn: function (type, args, obj) { },
5158
* The default onStart handler for the out-animation.
5159
* @method handleStartAnimateOut
5160
* @param {String} type The CustomEvent type
5161
* @param {Object[]} args The CustomEvent arguments
5162
* @param {Object} obj The scope object
5164
handleStartAnimateOut: function (type, args, obj) { },
5167
* The default onTween handler for the out-animation.
5168
* @method handleTweenAnimateOut
5169
* @param {String} type The CustomEvent type
5170
* @param {Object[]} args The CustomEvent arguments
5171
* @param {Object} obj The scope object
5173
handleTweenAnimateOut: function (type, args, obj) { },
5176
* The default onComplete handler for the out-animation.
5177
* @method handleCompleteAnimateOut
5178
* @param {String} type The CustomEvent type
5179
* @param {Object[]} args The CustomEvent arguments
5180
* @param {Object} obj The scope object
5182
handleCompleteAnimateOut: function (type, args, obj) { },
5185
* Returns a string representation of the object.
5187
* @return {String} The string representation of the ContainerEffect
5189
toString: function () {
5190
var output = "ContainerEffect";
5192
output += " [" + this.overlay.toString() + "]";
5198
YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
5202
YAHOO.register("containercore", YAHOO.widget.Module, {version: "2.7.0", build: "1799"});