2
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3
3
Code licensed under the BSD License:
4
4
http://developer.yahoo.net/yui/license.txt
8
* Config is a utility used within an Object to allow the implementer to maintain a list of local configuration properties and listen for changes to those properties dynamically using CustomEvent. The initial values are also maintained so that the configuration can be reset at any given point to its initial state.
9
* @namespace YAHOO.util
12
* @param {Object} owner The owner Object to which this Config Object belongs
14
YAHOO.util.Config = function(owner) {
18
YAHOO.log("No owner specified for Config object", "error");
22
YAHOO.util.Config.prototype = {
25
* Object reference to the owner of this Config Object
32
* Boolean flag that specifies whether a queue is currently being executed
33
* @property queueInProgress
36
queueInProgress : false,
40
* Validates that the value passed in is a Boolean.
41
* @method checkBoolean
42
* @param {Object} val The value to validate
43
* @return {Boolean} true, if the value is valid
45
checkBoolean: function(val) {
46
if (typeof val == 'boolean') {
54
* Validates that the value passed in is a number.
56
* @param {Object} val The value to validate
57
* @return {Boolean} true, if the value is valid
59
checkNumber: function(val) {
70
* Initializes the configuration Object and all of its local members.
72
* @param {Object} owner The owner Object to which this Config Object belongs
74
YAHOO.util.Config.prototype.init = function(owner) {
79
* Object reference to the owner of this Config Object
80
* @event configChangedEvent
82
this.configChangedEvent = new YAHOO.util.CustomEvent("configChanged");
83
this.queueInProgress = false;
88
* Maintains the local collection of configuration property objects and their specified values
96
* Maintains the local collection of configuration property objects as they were initially applied.
97
* This object is used when resetting a property.
98
* @property initialConfig
102
var initialConfig = {};
105
* Maintains the local, normalized CustomEvent queue
106
* @property eventQueue
113
* Fires a configuration property event using the specified value.
116
* @param {String} key The configuration property's name
117
* @param {value} Object The value of the correct type for the property
119
var fireEvent = function( key, value ) {
120
YAHOO.log("Firing Config event: " + key + "=" + value, "info");
122
key = key.toLowerCase();
124
var property = config[key];
126
if (typeof property != 'undefined' && property.event) {
127
property.event.fire(value);
130
/* End Private Members */
133
* Adds a property to the Config Object's private config hash.
134
* @method addProperty
135
* @param {String} key The configuration property's name
136
* @param {Object} propertyObject The Object containing all of this property's arguments
138
this.addProperty = function( key, propertyObject ) {
139
key = key.toLowerCase();
141
YAHOO.log("Added property: " + key, "info");
143
config[key] = propertyObject;
145
propertyObject.event = new YAHOO.util.CustomEvent(key);
146
propertyObject.key = key;
148
if (propertyObject.handler) {
149
propertyObject.event.subscribe(propertyObject.handler, this.owner, true);
152
this.setProperty(key, propertyObject.value, true);
154
if (! propertyObject.suppressEvent) {
155
this.queueProperty(key, propertyObject.value);
160
* Returns a key-value configuration map of the values currently set in the Config Object.
162
* @return {Object} The current config, represented in a key-value map
164
this.getConfig = function() {
167
for (var prop in config) {
168
var property = config[prop];
169
if (typeof property != 'undefined' && property.event) {
170
cfg[prop] = property.value;
178
* Returns the value of specified property.
179
* @method getProperty
180
* @param {String} key The name of the property
181
* @return {Object} The value of the specified property
183
this.getProperty = function(key) {
184
key = key.toLowerCase();
186
var property = config[key];
187
if (typeof property != 'undefined' && property.event) {
188
return property.value;
195
* Resets the specified property's value to its initial value.
196
* @method resetProperty
197
* @param {String} key The name of the property
198
* @return {Boolean} True is the property was reset, false if not
200
this.resetProperty = function(key) {
201
key = key.toLowerCase();
203
var property = config[key];
204
if (typeof property != 'undefined' && property.event) {
205
if (initialConfig[key] && initialConfig[key] != 'undefined') {
206
this.setProperty(key, initialConfig[key]);
215
* Sets the value of a property. If the silent property is passed as true, the property's event will not be fired.
216
* @method setProperty
217
* @param {String} key The name of the property
218
* @param {String} value The value to set the property to
219
* @param {Boolean} silent Whether the value should be set silently, without firing the property event.
220
* @return {Boolean} True, if the set was successful, false if it failed.
222
this.setProperty = function(key, value, silent) {
223
key = key.toLowerCase();
225
YAHOO.log("setProperty: " + key + "=" + value, "info");
227
if (this.queueInProgress && ! silent) {
228
this.queueProperty(key,value); // Currently running through a queue...
231
var property = config[key];
232
if (typeof property != 'undefined' && property.event) {
233
if (property.validator && ! property.validator(value)) { // validator
236
property.value = value;
238
fireEvent(key, value);
239
this.configChangedEvent.fire([key, value]);
250
* Sets the value of a property and queues its event to execute. If the event is already scheduled to execute, it is
251
* moved from its current position to the end of the queue.
252
* @method queueProperty
253
* @param {String} key The name of the property
254
* @param {String} value The value to set the property to
255
* @return {Boolean} true, if the set was successful, false if it failed.
257
this.queueProperty = function(key, value) {
258
key = key.toLowerCase();
260
YAHOO.log("queueProperty: " + key + "=" + value, "info");
262
var property = config[key];
264
if (typeof property != 'undefined' && property.event) {
265
if (typeof value != 'undefined' && property.validator && ! property.validator(value)) { // validator
269
if (typeof value != 'undefined') {
270
property.value = value;
272
value = property.value;
275
var foundDuplicate = false;
277
for (var i=0;i<eventQueue.length;i++) {
278
var queueItem = eventQueue[i];
281
var queueItemKey = queueItem[0];
282
var queueItemValue = queueItem[1];
284
if (queueItemKey.toLowerCase() == key) {
285
// found a dupe... push to end of queue, null current item, and break
286
eventQueue[i] = null;
287
eventQueue.push([key, (typeof value != 'undefined' ? value : queueItemValue)]);
288
foundDuplicate = true;
294
if (! foundDuplicate && typeof value != 'undefined') { // this is a refire, or a new property in the queue
295
eventQueue.push([key, value]);
299
if (property.supercedes) {
300
for (var s=0;s<property.supercedes.length;s++) {
301
var supercedesCheck = property.supercedes[s];
303
for (var q=0;q<eventQueue.length;q++) {
304
var queueItemCheck = eventQueue[q];
306
if (queueItemCheck) {
307
var queueItemCheckKey = queueItemCheck[0];
308
var queueItemCheckValue = queueItemCheck[1];
310
if ( queueItemCheckKey.toLowerCase() == supercedesCheck.toLowerCase() ) {
311
eventQueue.push([queueItemCheckKey, queueItemCheckValue]);
312
eventQueue[q] = null;
320
YAHOO.log("Config event queue: " + this.outputEventQueue(), "info");
329
* Fires the event for a property using the property's current value.
330
* @method refireEvent
331
* @param {String} key The name of the property
333
this.refireEvent = function(key) {
334
key = key.toLowerCase();
336
var property = config[key];
337
if (typeof property != 'undefined' && property.event && typeof property.value != 'undefined') {
338
if (this.queueInProgress) {
339
this.queueProperty(key);
341
fireEvent(key, property.value);
347
* Applies a key-value Object literal to the configuration, replacing any existing values, and queueing the property events.
348
* Although the values will be set, fireQueue() must be called for their associated events to execute.
349
* @method applyConfig
350
* @param {Object} userConfig The configuration Object literal
351
* @param {Boolean} init When set to true, the initialConfig will be set to the userConfig passed in, so that calling a reset will reset the properties to the passed values.
353
this.applyConfig = function(userConfig, init) {
355
initialConfig = userConfig;
357
for (var prop in userConfig) {
358
this.queueProperty(prop, userConfig[prop]);
363
* Refires the events for all configuration properties using their current values.
366
this.refresh = function() {
367
for (var prop in config) {
368
this.refireEvent(prop);
373
* Fires the normalized list of queued property change events
376
this.fireQueue = function() {
377
this.queueInProgress = true;
378
for (var i=0;i<eventQueue.length;i++) {
379
var queueItem = eventQueue[i];
381
var key = queueItem[0];
382
var value = queueItem[1];
384
var property = config[key];
385
property.value = value;
387
fireEvent(key,value);
391
this.queueInProgress = false;
396
* Subscribes an external handler to the change event for any given property.
397
* @method subscribeToConfigEvent
398
* @param {String} key The property name
399
* @param {Function} handler The handler function to use subscribe to the property's event
400
* @param {Object} obj The Object to use for scoping the event handler (see CustomEvent documentation)
401
* @param {Boolean} override Optional. If true, will override "this" within the handler to map to the scope Object passed into the method.
402
* @return {Boolean} True, if the subscription was successful, otherwise false.
404
this.subscribeToConfigEvent = function(key, handler, obj, override) {
405
key = key.toLowerCase();
407
var property = config[key];
408
if (typeof property != 'undefined' && property.event) {
409
if (! YAHOO.util.Config.alreadySubscribed(property.event, handler, obj)) {
410
property.event.subscribe(handler, obj, override);
419
* Unsubscribes an external handler from the change event for any given property.
420
* @method unsubscribeFromConfigEvent
421
* @param {String} key The property name
422
* @param {Function} handler The handler function to use subscribe to the property's event
423
* @param {Object} obj The Object to use for scoping the event handler (see CustomEvent documentation)
424
* @return {Boolean} True, if the unsubscription was successful, otherwise false.
426
this.unsubscribeFromConfigEvent = function(key, handler, obj) {
427
key = key.toLowerCase();
429
var property = config[key];
430
if (typeof property != 'undefined' && property.event) {
431
return property.event.unsubscribe(handler, obj);
438
* Returns a string representation of the Config object
440
* @return {String} The Config object in string format.
442
this.toString = function() {
443
var output = "Config";
445
output += " [" + this.owner.toString() + "]";
451
* Returns a string representation of the Config object's current CustomEvent queue
452
* @method outputEventQueue
453
* @return {String} The string list of CustomEvents currently queued for execution
455
this.outputEventQueue = function() {
457
for (var q=0;q<eventQueue.length;q++) {
458
var queueItem = eventQueue[q];
460
output += queueItem[0] + "=" + queueItem[1] + ", ";
468
* Checks to determine if a particular function/Object pair are already subscribed to the specified CustomEvent
469
* @method YAHOO.util.Config.alreadySubscribed
471
* @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check the subscriptions
472
* @param {Function} fn The function to look for in the subscribers list
473
* @param {Object} obj The execution scope Object for the subscription
474
* @return {Boolean} true, if the function/Object pair is already subscribed to the CustomEvent passed in
476
YAHOO.util.Config.alreadySubscribed = function(evt, fn, obj) {
477
for (var e=0;e<evt.subscribers.length;e++) {
478
var subsc = evt.subscribers[e];
479
if (subsc && subsc.obj == obj && subsc.fn == fn) {
487
* The Container family of components is designed to enable developers to create different kinds of content-containing modules on the web. Module and Overlay are the most basic containers, and they can be used directly or extended to build custom containers. Also part of the Container family are four UI controls that extend Module and Overlay: Tooltip, Panel, Dialog, and SimpleDialog.
490
* @requires yahoo,dom,event,dragdrop,animation
494
* Module is a JavaScript representation of the Standard Module Format. Standard Module Format is a simple standard for markup containers where child nodes representing the header, body, and footer of the content are denoted using the CSS classes "hd", "bd", and "ft" respectively. Module is the base class for all other classes in the YUI Container package.
495
* @namespace YAHOO.widget
498
* @param {String} el The element ID representing the Module <em>OR</em>
499
* @param {HTMLElement} el The element representing the Module
500
* @param {Object} userConfig The configuration Object literal containing the configuration that should be set for this module. See configuration documentation for more details.
502
YAHOO.widget.Module = function(el, userConfig) {
504
this.init(el, userConfig);
506
YAHOO.log("No element or element ID specified for Module instantiation", "error");
511
* Constant representing the prefix path to use for non-secure images
512
* @property YAHOO.widget.Module.IMG_ROOT
517
YAHOO.widget.Module.IMG_ROOT = "http://us.i1.yimg.com/us.yimg.com/i/";
520
* Constant representing the prefix path to use for securely served images
521
* @property YAHOO.widget.Module.IMG_ROOT_SSL
526
YAHOO.widget.Module.IMG_ROOT_SSL = "https://a248.e.akamai.net/sec.yimg.com/i/";
529
* Constant for the default CSS class name that represents a Module
530
* @property YAHOO.widget.Module.CSS_MODULE
535
YAHOO.widget.Module.CSS_MODULE = "module";
538
* Constant representing the module header
539
* @property YAHOO.widget.Module.CSS_HEADER
544
YAHOO.widget.Module.CSS_HEADER = "hd";
547
* Constant representing the module body
548
* @property YAHOO.widget.Module.CSS_BODY
553
YAHOO.widget.Module.CSS_BODY = "bd";
556
* Constant representing the module footer
557
* @property YAHOO.widget.Module.CSS_FOOTER
562
YAHOO.widget.Module.CSS_FOOTER = "ft";
565
* Constant representing the url for the "src" attribute of the iframe used to monitor changes to the browser's base font size
566
* @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
571
YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
574
* Singleton CustomEvent fired when the font size is changed in the browser.
575
* Opera's "zoom" functionality currently does not support text size detection.
576
* @event YAHOO.widget.Module.textResizeEvent
578
YAHOO.widget.Module.textResizeEvent = new YAHOO.util.CustomEvent("textResize");
580
YAHOO.widget.Module.prototype = {
582
* The class's constructor function
583
* @property contructor
586
constructor : YAHOO.widget.Module,
589
* The main module element that contains the header, body, and footer
596
* The header element, denoted with CSS class "hd"
603
* The body element, denoted with CSS class "bd"
610
* The footer element, denoted with CSS class "ft"
617
* The id of the element
624
* The String representing the image root
625
* @property imageRoot
628
imageRoot : YAHOO.widget.Module.IMG_ROOT,
631
* Initializes the custom events for Module which are fired automatically at appropriate times by the Module class.
634
initEvents : function() {
637
* CustomEvent fired prior to class initalization.
638
* @event beforeInitEvent
639
* @param {class} classRef class reference of the initializing class, such as this.beforeInitEvent.fire(YAHOO.widget.Module)
641
this.beforeInitEvent = new YAHOO.util.CustomEvent("beforeInit");
644
* CustomEvent fired after class initalization.
646
* @param {class} classRef class reference of the initializing class, such as this.beforeInitEvent.fire(YAHOO.widget.Module)
648
this.initEvent = new YAHOO.util.CustomEvent("init");
651
* CustomEvent fired when the Module is appended to the DOM
654
this.appendEvent = new YAHOO.util.CustomEvent("append");
657
* CustomEvent fired before the Module is rendered
658
* @event beforeRenderEvent
660
this.beforeRenderEvent = new YAHOO.util.CustomEvent("beforeRender");
663
* CustomEvent fired after the Module is rendered
666
this.renderEvent = new YAHOO.util.CustomEvent("render");
669
* CustomEvent fired when the header content of the Module is modified
670
* @event changeHeaderEvent
671
* @param {String/HTMLElement} content String/element representing the new header content
673
this.changeHeaderEvent = new YAHOO.util.CustomEvent("changeHeader");
676
* CustomEvent fired when the body content of the Module is modified
677
* @event changeBodyEvent
678
* @param {String/HTMLElement} content String/element representing the new body content
680
this.changeBodyEvent = new YAHOO.util.CustomEvent("changeBody");
683
* CustomEvent fired when the footer content of the Module is modified
684
* @event changeFooterEvent
685
* @param {String/HTMLElement} content String/element representing the new footer content
687
this.changeFooterEvent = new YAHOO.util.CustomEvent("changeFooter");
690
* CustomEvent fired when the content of the Module is modified
691
* @event changeContentEvent
693
this.changeContentEvent = new YAHOO.util.CustomEvent("changeContent");
696
* CustomEvent fired when the Module is destroyed
697
* @event destroyEvent
699
this.destroyEvent = new YAHOO.util.CustomEvent("destroy");
702
* CustomEvent fired before the Module is shown
703
* @event beforeShowEvent
705
this.beforeShowEvent = new YAHOO.util.CustomEvent("beforeShow");
708
* CustomEvent fired after the Module is shown
711
this.showEvent = new YAHOO.util.CustomEvent("show");
714
* CustomEvent fired before the Module is hidden
715
* @event beforeHideEvent
717
this.beforeHideEvent = new YAHOO.util.CustomEvent("beforeHide");
720
* CustomEvent fired after the Module is hidden
723
this.hideEvent = new YAHOO.util.CustomEvent("hide");
727
* String representing the current user-agent platform
731
platform : function() {
732
var ua = navigator.userAgent.toLowerCase();
733
if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
735
} else if (ua.indexOf("macintosh") != -1) {
743
* String representing the current user-agent browser
747
browser : function() {
748
var ua = navigator.userAgent.toLowerCase();
749
if (ua.indexOf('opera')!=-1) { // Opera (check first in case of spoof)
751
} else if (ua.indexOf('msie 7')!=-1) { // IE7
753
} else if (ua.indexOf('msie') !=-1) { // IE
755
} else if (ua.indexOf('safari')!=-1) { // Safari (check before Gecko because it includes "like Gecko")
757
} else if (ua.indexOf('gecko') != -1) { // Gecko
765
* Boolean representing whether or not the current browsing context is secure (https)
769
isSecure : function() {
770
if (window.location.href.toLowerCase().indexOf("https") === 0) {
778
* Initializes the custom events for Module which are fired automatically at appropriate times by the Module class.
780
initDefaultConfig : function() {
784
* Specifies whether the Module is visible on the page.
789
this.cfg.addProperty("visible", { value:true, handler:this.configVisible, validator:this.cfg.checkBoolean } );
792
* Object or array of objects representing the ContainerEffect classes that are active for animating the container.
797
this.cfg.addProperty("effect", { suppressEvent:true, supercedes:["visible"] } );
800
* Specifies whether to create a special proxy iframe to monitor for user font resizing in the document
801
* @config monitorresize
805
this.cfg.addProperty("monitorresize", { value:true, handler:this.configMonitorResize } );
809
* The Module class's initialization method, which is executed for Module and all of its subclasses. This method is automatically called by the constructor, and sets up all DOM references for pre-existing markup, and creates required markup if it is not already present.
811
* @param {String} el The element ID representing the Module <em>OR</em>
812
* @param {HTMLElement} el The element representing the Module
813
* @param {Object} userConfig The configuration Object literal containing the configuration that should be set for this module. See configuration documentation for more details.
815
init : function(el, userConfig) {
819
this.beforeInitEvent.fire(YAHOO.widget.Module);
822
* The Module's Config object used for monitoring configuration properties.
824
* @type YAHOO.util.Config
826
this.cfg = new YAHOO.util.Config(this);
829
this.imageRoot = YAHOO.widget.Module.IMG_ROOT_SSL;
832
if (typeof el == "string") {
835
el = document.getElementById(el);
837
el = document.createElement("DIV");
848
var childNodes = this.element.childNodes;
851
for (var i=0;i<childNodes.length;i++) {
852
var child = childNodes[i];
853
switch (child.className) {
854
case YAHOO.widget.Module.CSS_HEADER:
857
case YAHOO.widget.Module.CSS_BODY:
860
case YAHOO.widget.Module.CSS_FOOTER:
867
this.initDefaultConfig();
869
YAHOO.util.Dom.addClass(this.element, YAHOO.widget.Module.CSS_MODULE);
872
this.cfg.applyConfig(userConfig, true);
875
// Subscribe to the fireQueue() method of Config so that any queued configuration changes are
876
// excecuted upon render of the Module
877
if (! YAHOO.util.Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) {
878
this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
881
this.initEvent.fire(YAHOO.widget.Module);
885
* Initialized an empty IFRAME that is placed out of the visible area that can be used to detect text resize.
886
* @method initResizeMonitor
888
initResizeMonitor : function() {
890
if(this.browser != "opera") {
892
var resizeMonitor = document.getElementById("_yuiResizeMonitor");
894
if (! resizeMonitor) {
896
resizeMonitor = document.createElement("iframe");
898
var bIE = (this.browser.indexOf("ie") === 0);
901
YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL &&
905
YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL;
909
resizeMonitor.id = "_yuiResizeMonitor";
910
resizeMonitor.style.visibility = "hidden";
912
document.body.appendChild(resizeMonitor);
914
resizeMonitor.style.width = "10em";
915
resizeMonitor.style.height = "10em";
916
resizeMonitor.style.position = "absolute";
918
var nLeft = -1 * resizeMonitor.offsetWidth,
919
nTop = -1 * resizeMonitor.offsetHeight;
921
resizeMonitor.style.top = nTop + "px";
922
resizeMonitor.style.left = nLeft + "px";
923
resizeMonitor.style.borderStyle = "none";
924
resizeMonitor.style.borderWidth = "0";
925
YAHOO.util.Dom.setStyle(resizeMonitor, "opacity", "0");
927
resizeMonitor.style.visibility = "visible";
931
var doc = resizeMonitor.contentWindow.document;
939
var fireTextResize = function() {
940
YAHOO.widget.Module.textResizeEvent.fire();
943
if(resizeMonitor && resizeMonitor.contentWindow) {
944
this.resizeMonitor = resizeMonitor;
946
YAHOO.widget.Module.textResizeEvent.subscribe(this.onDomResize, this, true);
948
if (! YAHOO.widget.Module.textResizeInitialized) {
949
if (! YAHOO.util.Event.addListener(this.resizeMonitor.contentWindow, "resize", fireTextResize)) {
950
// This will fail in IE if document.domain has changed, so we must change the listener to
951
// use the resizeMonitor element instead
952
YAHOO.util.Event.addListener(this.resizeMonitor, "resize", fireTextResize);
954
YAHOO.widget.Module.textResizeInitialized = true;
963
* Event handler fired when the resize monitor element is resized.
964
* @method onDomResize
965
* @param {DOMEvent} e The DOM resize event
966
* @param {Object} obj The scope object passed to the handler
968
onDomResize : function(e, obj) {
970
var nLeft = -1 * this.resizeMonitor.offsetWidth,
971
nTop = -1 * this.resizeMonitor.offsetHeight;
973
this.resizeMonitor.style.top = nTop + "px";
974
this.resizeMonitor.style.left = nLeft + "px";
979
* Sets the Module's header content to the HTML specified, or appends the passed element to the header. If no header is present, one will be automatically created.
981
* @param {String} headerContent The HTML used to set the header <em>OR</em>
982
* @param {HTMLElement} headerContent The HTMLElement to append to the header
984
setHeader : function(headerContent) {
986
this.header = document.createElement("DIV");
987
this.header.className = YAHOO.widget.Module.CSS_HEADER;
990
if (typeof headerContent == "string") {
991
this.header.innerHTML = headerContent;
993
this.header.innerHTML = "";
994
this.header.appendChild(headerContent);
997
this.changeHeaderEvent.fire(headerContent);
998
this.changeContentEvent.fire();
1002
* Appends the passed element to the header. If no header is present, one will be automatically created.
1003
* @method appendToHeader
1004
* @param {HTMLElement} element The element to append to the header
1006
appendToHeader : function(element) {
1007
if (! this.header) {
1008
this.header = document.createElement("DIV");
1009
this.header.className = YAHOO.widget.Module.CSS_HEADER;
1012
this.header.appendChild(element);
1013
this.changeHeaderEvent.fire(element);
1014
this.changeContentEvent.fire();
1018
* Sets the Module's body content to the HTML specified, or appends the passed element to the body. If no body is present, one will be automatically created.
1020
* @param {String} bodyContent The HTML used to set the body <em>OR</em>
1021
* @param {HTMLElement} bodyContent The HTMLElement to append to the body
1023
setBody : function(bodyContent) {
1025
this.body = document.createElement("DIV");
1026
this.body.className = YAHOO.widget.Module.CSS_BODY;
1029
if (typeof bodyContent == "string")
1031
this.body.innerHTML = bodyContent;
1033
this.body.innerHTML = "";
1034
this.body.appendChild(bodyContent);
1037
this.changeBodyEvent.fire(bodyContent);
1038
this.changeContentEvent.fire();
1042
* Appends the passed element to the body. If no body is present, one will be automatically created.
1043
* @method appendToBody
1044
* @param {HTMLElement} element The element to append to the body
1046
appendToBody : function(element) {
1048
this.body = document.createElement("DIV");
1049
this.body.className = YAHOO.widget.Module.CSS_BODY;
1052
this.body.appendChild(element);
1053
this.changeBodyEvent.fire(element);
1054
this.changeContentEvent.fire();
1058
* Sets the Module's footer content to the HTML specified, or appends the passed element to the footer. If no footer is present, one will be automatically created.
1060
* @param {String} footerContent The HTML used to set the footer <em>OR</em>
1061
* @param {HTMLElement} footerContent The HTMLElement to append to the footer
1063
setFooter : function(footerContent) {
1064
if (! this.footer) {
1065
this.footer = document.createElement("DIV");
1066
this.footer.className = YAHOO.widget.Module.CSS_FOOTER;
1069
if (typeof footerContent == "string") {
1070
this.footer.innerHTML = footerContent;
1072
this.footer.innerHTML = "";
1073
this.footer.appendChild(footerContent);
1076
this.changeFooterEvent.fire(footerContent);
1077
this.changeContentEvent.fire();
1081
* Appends the passed element to the footer. If no footer is present, one will be automatically created.
1082
* @method appendToFooter
1083
* @param {HTMLElement} element The element to append to the footer
1085
appendToFooter : function(element) {
1086
if (! this.footer) {
1087
this.footer = document.createElement("DIV");
1088
this.footer.className = YAHOO.widget.Module.CSS_FOOTER;
1091
this.footer.appendChild(element);
1092
this.changeFooterEvent.fire(element);
1093
this.changeContentEvent.fire();
1097
* Renders the Module by inserting the elements that are not already in the main Module into their correct places. Optionally appends the Module to the specified node prior to the render's execution. NOTE: For Modules without existing markup, the appendToNode argument is REQUIRED. If this argument is ommitted and the current element is not present in the document, the function will return false, indicating that the render was a failure.
1099
* @param {String} appendToNode The element id to which the Module should be appended to prior to rendering <em>OR</em>
1100
* @param {HTMLElement} appendToNode The element to which the Module should be appended to prior to rendering
1101
* @param {HTMLElement} moduleElement OPTIONAL. The element that represents the actual Standard Module container.
1102
* @return {Boolean} Success or failure of the render
1104
render : function(appendToNode, moduleElement) {
1105
this.beforeRenderEvent.fire();
1107
if (! moduleElement) {
1108
moduleElement = this.element;
1112
var appendTo = function(element) {
1113
if (typeof element == "string") {
1114
element = document.getElementById(element);
1118
element.appendChild(me.element);
1119
me.appendEvent.fire();
1124
appendTo(appendToNode);
1125
} else { // No node was passed in. If the element is not pre-marked up, this fails
1126
if (! YAHOO.util.Dom.inDocument(this.element)) {
1127
YAHOO.log("Render failed. Must specify appendTo node if Module isn't already in the DOM.", "error");
1132
// Need to get everything into the DOM if it isn't already
1134
if (this.header && ! YAHOO.util.Dom.inDocument(this.header)) {
1135
// There is a header, but it's not in the DOM yet... need to add it
1136
var firstChild = moduleElement.firstChild;
1137
if (firstChild) { // Insert before first child if exists
1138
moduleElement.insertBefore(this.header, firstChild);
1139
} else { // Append to empty body because there are no children
1140
moduleElement.appendChild(this.header);
1144
if (this.body && ! YAHOO.util.Dom.inDocument(this.body)) {
1145
// There is a body, but it's not in the DOM yet... need to add it
1146
if (this.footer && YAHOO.util.Dom.isAncestor(this.moduleElement, this.footer)) { // Insert before footer if exists in DOM
1147
moduleElement.insertBefore(this.body, this.footer);
1148
} else { // Append to element because there is no footer
1149
moduleElement.appendChild(this.body);
1153
if (this.footer && ! YAHOO.util.Dom.inDocument(this.footer)) {
1154
// There is a footer, but it's not in the DOM yet... need to add it
1155
moduleElement.appendChild(this.footer);
1158
this.renderEvent.fire();
1163
* Removes the Module element from the DOM and sets all child elements to null.
1166
destroy : function() {
1170
YAHOO.util.Event.purgeElement(this.element, true);
1171
parent = this.element.parentNode;
1174
parent.removeChild(this.element);
1177
this.element = null;
1182
for (var e in this) {
1183
if (e instanceof YAHOO.util.CustomEvent) {
1188
YAHOO.widget.Module.textResizeEvent.unsubscribe(this.onDomResize, this);
1190
this.destroyEvent.fire();
1194
* Shows the Module element by setting the visible configuration property to true. Also fires two events: beforeShowEvent prior to the visibility change, and showEvent after.
1198
this.cfg.setProperty("visible", true);
1202
* Hides the Module element by setting the visible configuration property to false. Also fires two events: beforeHideEvent prior to the visibility change, and hideEvent after.
1206
this.cfg.setProperty("visible", false);
1209
// BUILT-IN EVENT HANDLERS FOR MODULE //
1212
* Default event handler for changing the visibility property of a Module. By default, this is achieved by switching the "display" style between "block" and "none".
1213
* This method is responsible for firing showEvent and hideEvent.
1214
* @param {String} type The CustomEvent type (usually the property name)
1215
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1216
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
1217
* @method configVisible
1219
configVisible : function(type, args, obj) {
1220
var visible = args[0];
1222
this.beforeShowEvent.fire();
1223
YAHOO.util.Dom.setStyle(this.element, "display", "block");
1224
this.showEvent.fire();
1226
this.beforeHideEvent.fire();
1227
YAHOO.util.Dom.setStyle(this.element, "display", "none");
1228
this.hideEvent.fire();
1233
* Default event handler for the "monitorresize" configuration property
1234
* @param {String} type The CustomEvent type (usually the property name)
1235
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1236
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
1237
* @method configMonitorResize
1239
configMonitorResize : function(type, args, obj) {
1240
var monitor = args[0];
1242
this.initResizeMonitor();
1244
YAHOO.widget.Module.textResizeEvent.unsubscribe(this.onDomResize, this, true);
1245
this.resizeMonitor = null;
1251
* Returns a String representation of the Object.
1253
* @return {String} The string representation of the Module
1255
YAHOO.widget.Module.prototype.toString = function() {
1256
return "Module " + this.id;
1260
* Overlay is a Module that is absolutely positioned above the page flow. It has convenience methods for positioning and sizing, as well as options for controlling zIndex and constraining the Overlay's position to the current visible viewport. Overlay also contains a dynamicly generated IFRAME which is placed beneath it for Internet Explorer 6 and 5.x so that it will be properly rendered above SELECT elements.
1261
* @namespace YAHOO.widget
1263
* @extends YAHOO.widget.Module
1264
* @param {String} el The element ID representing the Overlay <em>OR</em>
1265
* @param {HTMLElement} el The element representing the Overlay
1266
* @param {Object} userConfig The configuration object literal containing 10/23/2006the configuration that should be set for this Overlay. See configuration documentation for more details.
1269
YAHOO.widget.Overlay = function(el, userConfig) {
1270
YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
1273
YAHOO.extend(YAHOO.widget.Overlay, YAHOO.widget.Module);
1276
* The URL that will be placed in the iframe
1277
* @property YAHOO.widget.Overlay.IFRAME_SRC
1282
YAHOO.widget.Overlay.IFRAME_SRC = "javascript:false;";
1285
* Constant representing the top left corner of an element, used for configuring the context element alignment
1286
* @property YAHOO.widget.Overlay.TOP_LEFT
1291
YAHOO.widget.Overlay.TOP_LEFT = "tl";
1294
* Constant representing the top right corner of an element, used for configuring the context element alignment
1295
* @property YAHOO.widget.Overlay.TOP_RIGHT
1300
YAHOO.widget.Overlay.TOP_RIGHT = "tr";
1303
* Constant representing the top bottom left corner of an element, used for configuring the context element alignment
1304
* @property YAHOO.widget.Overlay.BOTTOM_LEFT
1309
YAHOO.widget.Overlay.BOTTOM_LEFT = "bl";
1312
* Constant representing the bottom right corner of an element, used for configuring the context element alignment
1313
* @property YAHOO.widget.Overlay.BOTTOM_RIGHT
1318
YAHOO.widget.Overlay.BOTTOM_RIGHT = "br";
1321
* Constant representing the default CSS class used for an Overlay
1322
* @property YAHOO.widget.Overlay.CSS_OVERLAY
1327
YAHOO.widget.Overlay.CSS_OVERLAY = "overlay";
1330
* The Overlay initialization method, which is executed for Overlay and all of its subclasses. This method is automatically called by the constructor, and sets up all DOM references for pre-existing markup, and creates required markup if it is not already present.
1332
* @param {String} el The element ID representing the Overlay <em>OR</em>
1333
* @param {HTMLElement} el The element representing the Overlay
1334
* @param {Object} userConfig The configuration object literal containing the configuration that should be set for this Overlay. See configuration documentation for more details.
1336
YAHOO.widget.Overlay.prototype.init = function(el, userConfig) {
1337
YAHOO.widget.Overlay.superclass.init.call(this, el/*, userConfig*/); // Note that we don't pass the user config in here yet because we only want it executed once, at the lowest subclass level
1339
this.beforeInitEvent.fire(YAHOO.widget.Overlay);
1341
YAHOO.util.Dom.addClass(this.element, YAHOO.widget.Overlay.CSS_OVERLAY);
1344
this.cfg.applyConfig(userConfig, true);
1347
if (this.platform == "mac" && this.browser == "gecko") {
1348
if (! YAHOO.util.Config.alreadySubscribed(this.showEvent,this.showMacGeckoScrollbars,this)) {
1349
this.showEvent.subscribe(this.showMacGeckoScrollbars,this,true);
1351
if (! YAHOO.util.Config.alreadySubscribed(this.hideEvent,this.hideMacGeckoScrollbars,this)) {
1352
this.hideEvent.subscribe(this.hideMacGeckoScrollbars,this,true);
1356
this.initEvent.fire(YAHOO.widget.Overlay);
1361
* Initializes the custom events for Overlay which are fired automatically at appropriate times by the Overlay class.
1362
* @method initEvents
1364
YAHOO.widget.Overlay.prototype.initEvents = function() {
1365
YAHOO.widget.Overlay.superclass.initEvents.call(this);
1368
* CustomEvent fired before the Overlay is moved.
1369
* @event beforeMoveEvent
1370
* @param {Number} x x coordinate
1371
* @param {Number} y y coordinate
1373
this.beforeMoveEvent = new YAHOO.util.CustomEvent("beforeMove", this);
1376
* CustomEvent fired after the Overlay is moved.
1378
* @param {Number} x x coordinate
1379
* @param {Number} y y coordinate
1381
this.moveEvent = new YAHOO.util.CustomEvent("move", this);
1385
* Initializes the class's configurable properties which can be changed using the Overlay's Config object (cfg).
1386
* @method initDefaultConfig
1388
YAHOO.widget.Overlay.prototype.initDefaultConfig = function() {
1389
YAHOO.widget.Overlay.superclass.initDefaultConfig.call(this);
1391
// Add overlay config properties //
1394
* The absolute x-coordinate position of the Overlay
1399
this.cfg.addProperty("x", { handler:this.configX, validator:this.cfg.checkNumber, suppressEvent:true, supercedes:["iframe"] } );
1402
* The absolute y-coordinate position of the Overlay
1407
this.cfg.addProperty("y", { handler:this.configY, validator:this.cfg.checkNumber, suppressEvent:true, supercedes:["iframe"] } );
1410
* An array with the absolute x and y positions of the Overlay
1415
this.cfg.addProperty("xy",{ handler:this.configXY, suppressEvent:true, supercedes:["iframe"] } );
1418
* The array of context arguments for context-sensitive positioning. The format is: [id or element, element corner, context corner]. For example, setting this property to ["img1", "tl", "bl"] would align the Overlay's top left corner to the context element's bottom left corner.
1423
this.cfg.addProperty("context", { handler:this.configContext, suppressEvent:true, supercedes:["iframe"] } );
1426
* True if the Overlay should be anchored to the center of the viewport.
1427
* @config fixedcenter
1431
this.cfg.addProperty("fixedcenter", { value:false, handler:this.configFixedCenter, validator:this.cfg.checkBoolean, supercedes:["iframe","visible"] } );
1434
* CSS width of the Overlay.
1439
this.cfg.addProperty("width", { handler:this.configWidth, suppressEvent:true, supercedes:["iframe"] } );
1442
* CSS height of the Overlay.
1447
this.cfg.addProperty("height", { handler:this.configHeight, suppressEvent:true, supercedes:["iframe"] } );
1450
* CSS z-index of the Overlay.
1455
this.cfg.addProperty("zIndex", { value:null, handler:this.configzIndex } );
1458
* True if the Overlay should be prevented from being positioned out of the viewport.
1459
* @config constraintoviewport
1463
this.cfg.addProperty("constraintoviewport", { value:false, handler:this.configConstrainToViewport, validator:this.cfg.checkBoolean, supercedes:["iframe","x","y","xy"] } );
1466
* True if the Overlay should have an IFRAME shim (for correcting the select z-index bug in IE6 and below).
1469
* @default true for IE6 and below, false for all others
1471
this.cfg.addProperty("iframe", { value:(this.browser == "ie" ? true : false), handler:this.configIframe, validator:this.cfg.checkBoolean, supercedes:["zIndex"] } );
1475
* Moves the Overlay to the specified position. This function is identical to calling this.cfg.setProperty("xy", [x,y]);
1477
* @param {Number} x The Overlay's new x position
1478
* @param {Number} y The Overlay's new y position
1480
YAHOO.widget.Overlay.prototype.moveTo = function(x, y) {
1481
this.cfg.setProperty("xy",[x,y]);
1485
* Adds a special CSS class to the Overlay when Mac/Gecko is in use, to work around a Gecko bug where
1486
* scrollbars cannot be hidden. See https://bugzilla.mozilla.org/show_bug.cgi?id=187435
1487
* @method hideMacGeckoScrollbars
1489
YAHOO.widget.Overlay.prototype.hideMacGeckoScrollbars = function() {
1490
YAHOO.util.Dom.removeClass(this.element, "show-scrollbars");
1491
YAHOO.util.Dom.addClass(this.element, "hide-scrollbars");
1495
* Removes a special CSS class from the Overlay when Mac/Gecko is in use, to work around a Gecko bug where
1496
* scrollbars cannot be hidden. See https://bugzilla.mozilla.org/show_bug.cgi?id=187435
1497
* @method showMacGeckoScrollbars
1499
YAHOO.widget.Overlay.prototype.showMacGeckoScrollbars = function() {
1500
YAHOO.util.Dom.removeClass(this.element, "hide-scrollbars");
1501
YAHOO.util.Dom.addClass(this.element, "show-scrollbars");
1504
// BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
1507
* The default event handler fired when the "visible" property is changed. This method is responsible for firing showEvent and hideEvent.
1508
* @method configVisible
1509
* @param {String} type The CustomEvent type (usually the property name)
1510
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1511
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
1513
YAHOO.widget.Overlay.prototype.configVisible = function(type, args, obj) {
1514
var visible = args[0];
1515
var currentVis = YAHOO.util.Dom.getStyle(this.element, "visibility");
1517
if (currentVis == "inherit") {
1518
var e = this.element.parentNode;
1519
while (e.nodeType != 9 && e.nodeType != 11) {
1520
currentVis = YAHOO.util.Dom.getStyle(e, "visibility");
1521
if (currentVis != "inherit") { break; }
1524
if (currentVis == "inherit") {
1525
currentVis = "visible";
1529
var effect = this.cfg.getProperty("effect");
1531
var effectInstances = [];
1533
if (effect instanceof Array) {
1534
for (var i=0;i<effect.length;i++) {
1535
var eff = effect[i];
1536
effectInstances[effectInstances.length] = eff.effect(this, eff.duration);
1539
effectInstances[effectInstances.length] = effect.effect(this, effect.duration);
1543
var isMacGecko = (this.platform == "mac" && this.browser == "gecko");
1545
if (visible) { // Show
1547
this.showMacGeckoScrollbars();
1550
if (effect) { // Animate in
1551
if (visible) { // Animate in if not showing
1552
if (currentVis != "visible" || currentVis === "") {
1553
this.beforeShowEvent.fire();
1554
for (var j=0;j<effectInstances.length;j++) {
1555
var ei = effectInstances[j];
1556
if (j === 0 && ! YAHOO.util.Config.alreadySubscribed(ei.animateInCompleteEvent,this.showEvent.fire,this.showEvent)) {
1557
ei.animateInCompleteEvent.subscribe(this.showEvent.fire,this.showEvent,true); // Delegate showEvent until end of animateInComplete
1564
if (currentVis != "visible" || currentVis === "") {
1565
this.beforeShowEvent.fire();
1566
YAHOO.util.Dom.setStyle(this.element, "visibility", "visible");
1567
this.cfg.refireEvent("iframe");
1568
this.showEvent.fire();
1574
this.hideMacGeckoScrollbars();
1577
if (effect) { // Animate out if showing
1578
if (currentVis == "visible") {
1579
this.beforeHideEvent.fire();
1580
for (var k=0;k<effectInstances.length;k++) {
1581
var h = effectInstances[k];
1582
if (k === 0 && ! YAHOO.util.Config.alreadySubscribed(h.animateOutCompleteEvent,this.hideEvent.fire,this.hideEvent)) {
1583
h.animateOutCompleteEvent.subscribe(this.hideEvent.fire,this.hideEvent,true); // Delegate hideEvent until end of animateOutComplete
1587
} else if (currentVis === "") {
1588
YAHOO.util.Dom.setStyle(this.element, "visibility", "hidden");
1590
} else { // Simple hide
1591
if (currentVis == "visible" || currentVis === "") {
1592
this.beforeHideEvent.fire();
1593
YAHOO.util.Dom.setStyle(this.element, "visibility", "hidden");
1594
this.cfg.refireEvent("iframe");
1595
this.hideEvent.fire();
1602
* Center event handler used for centering on scroll/resize, but only if the Overlay is visible
1603
* @method doCenterOnDOMEvent
1605
YAHOO.widget.Overlay.prototype.doCenterOnDOMEvent = function() {
1606
if (this.cfg.getProperty("visible")) {
1612
* The default event handler fired when the "fixedcenter" property is changed.
1613
* @method configFixedCenter
1614
* @param {String} type The CustomEvent type (usually the property name)
1615
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1616
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
1618
YAHOO.widget.Overlay.prototype.configFixedCenter = function(type, args, obj) {
1624
if (! YAHOO.util.Config.alreadySubscribed(this.beforeShowEvent, this.center, this)) {
1625
this.beforeShowEvent.subscribe(this.center, this, true);
1628
if (! YAHOO.util.Config.alreadySubscribed(YAHOO.widget.Overlay.windowResizeEvent, this.doCenterOnDOMEvent, this)) {
1629
YAHOO.widget.Overlay.windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
1632
if (! YAHOO.util.Config.alreadySubscribed(YAHOO.widget.Overlay.windowScrollEvent, this.doCenterOnDOMEvent, this)) {
1633
YAHOO.widget.Overlay.windowScrollEvent.subscribe( this.doCenterOnDOMEvent, this, true);
1636
YAHOO.widget.Overlay.windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
1637
YAHOO.widget.Overlay.windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
1642
* The default event handler fired when the "height" property is changed.
1643
* @method configHeight
1644
* @param {String} type The CustomEvent type (usually the property name)
1645
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1646
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
1648
YAHOO.widget.Overlay.prototype.configHeight = function(type, args, obj) {
1649
var height = args[0];
1650
var el = this.element;
1651
YAHOO.util.Dom.setStyle(el, "height", height);
1652
this.cfg.refireEvent("iframe");
1656
* The default event handler fired when the "width" property is changed.
1657
* @method configWidth
1658
* @param {String} type The CustomEvent type (usually the property name)
1659
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1660
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
1662
YAHOO.widget.Overlay.prototype.configWidth = function(type, args, obj) {
1663
var width = args[0];
1664
var el = this.element;
1665
YAHOO.util.Dom.setStyle(el, "width", width);
1666
this.cfg.refireEvent("iframe");
1670
* The default event handler fired when the "zIndex" property is changed.
1671
* @method configzIndex
1672
* @param {String} type The CustomEvent type (usually the property name)
1673
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1674
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
1676
YAHOO.widget.Overlay.prototype.configzIndex = function(type, args, obj) {
1677
var zIndex = args[0];
1679
var el = this.element;
1682
zIndex = YAHOO.util.Dom.getStyle(el, "zIndex");
1683
if (! zIndex || isNaN(zIndex)) {
1692
YAHOO.util.Dom.setStyle(this.iframe, "zIndex", (zIndex-1));
1695
YAHOO.util.Dom.setStyle(el, "zIndex", zIndex);
1696
this.cfg.setProperty("zIndex", zIndex, true);
1700
* The default event handler fired when the "xy" property is changed.
1702
* @param {String} type The CustomEvent type (usually the property name)
1703
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1704
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
1706
YAHOO.widget.Overlay.prototype.configXY = function(type, args, obj) {
1711
this.cfg.setProperty("x", x);
1712
this.cfg.setProperty("y", y);
1714
this.beforeMoveEvent.fire([x,y]);
1716
x = this.cfg.getProperty("x");
1717
y = this.cfg.getProperty("y");
1719
YAHOO.log("xy: " + [x,y], "iframe");
1721
this.cfg.refireEvent("iframe");
1722
this.moveEvent.fire([x,y]);
1726
* The default event handler fired when the "x" property is changed.
1728
* @param {String} type The CustomEvent type (usually the property name)
1729
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1730
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
1732
YAHOO.widget.Overlay.prototype.configX = function(type, args, obj) {
1734
var y = this.cfg.getProperty("y");
1736
this.cfg.setProperty("x", x, true);
1737
this.cfg.setProperty("y", y, true);
1739
this.beforeMoveEvent.fire([x,y]);
1741
x = this.cfg.getProperty("x");
1742
y = this.cfg.getProperty("y");
1744
YAHOO.util.Dom.setX(this.element, x, true);
1746
this.cfg.setProperty("xy", [x, y], true);
1748
this.cfg.refireEvent("iframe");
1749
this.moveEvent.fire([x, y]);
1753
* The default event handler fired when the "y" property is changed.
1755
* @param {String} type The CustomEvent type (usually the property name)
1756
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1757
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
1759
YAHOO.widget.Overlay.prototype.configY = function(type, args, obj) {
1760
var x = this.cfg.getProperty("x");
1763
this.cfg.setProperty("x", x, true);
1764
this.cfg.setProperty("y", y, true);
1766
this.beforeMoveEvent.fire([x,y]);
1768
x = this.cfg.getProperty("x");
1769
y = this.cfg.getProperty("y");
1771
YAHOO.util.Dom.setY(this.element, y, true);
1773
this.cfg.setProperty("xy", [x, y], true);
1775
this.cfg.refireEvent("iframe");
1776
this.moveEvent.fire([x, y]);
1780
* Shows the iframe shim, if it has been enabled
1781
* @method showIframe
1783
YAHOO.widget.Overlay.prototype.showIframe = function() {
1785
this.iframe.style.display = "block";
1790
* Hides the iframe shim, if it has been enabled
1791
* @method hideIframe
1793
YAHOO.widget.Overlay.prototype.hideIframe = function() {
1795
this.iframe.style.display = "none";
1800
* The default event handler fired when the "iframe" property is changed.
1801
* @method configIframe
1802
* @param {String} type The CustomEvent type (usually the property name)
1803
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1804
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
1806
YAHOO.widget.Overlay.prototype.configIframe = function(type, args, obj) {
1810
if (val) { // IFRAME shim is enabled
1812
if (! YAHOO.util.Config.alreadySubscribed(this.showEvent, this.showIframe, this)) {
1813
this.showEvent.subscribe(this.showIframe, this, true);
1815
if (! YAHOO.util.Config.alreadySubscribed(this.hideEvent, this.hideIframe, this)) {
1816
this.hideEvent.subscribe(this.hideIframe, this, true);
1819
var x = this.cfg.getProperty("x");
1820
var y = this.cfg.getProperty("y");
1823
this.syncPosition();
1824
x = this.cfg.getProperty("x");
1825
y = this.cfg.getProperty("y");
1828
YAHOO.log("iframe positioning to: " + [x,y], "iframe");
1830
if (! isNaN(x) && ! isNaN(y)) {
1831
if (! this.iframe) {
1832
this.iframe = document.createElement("iframe");
1833
if (this.isSecure) {
1834
this.iframe.src = YAHOO.widget.Overlay.IFRAME_SRC;
1837
var parent = this.element.parentNode;
1839
parent.appendChild(this.iframe);
1841
document.body.appendChild(this.iframe);
1844
YAHOO.util.Dom.setStyle(this.iframe, "position", "absolute");
1845
YAHOO.util.Dom.setStyle(this.iframe, "border", "none");
1846
YAHOO.util.Dom.setStyle(this.iframe, "margin", "0");
1847
YAHOO.util.Dom.setStyle(this.iframe, "padding", "0");
1848
YAHOO.util.Dom.setStyle(this.iframe, "opacity", "0");
1849
if (this.cfg.getProperty("visible")) {
1856
var iframeDisplay = YAHOO.util.Dom.getStyle(this.iframe, "display");
1858
if (iframeDisplay == "none") {
1859
this.iframe.style.display = "block";
1862
YAHOO.util.Dom.setXY(this.iframe, [x,y]);
1864
var width = this.element.clientWidth;
1865
var height = this.element.clientHeight;
1867
YAHOO.util.Dom.setStyle(this.iframe, "width", (width+2) + "px");
1868
YAHOO.util.Dom.setStyle(this.iframe, "height", (height+2) + "px");
1870
if (iframeDisplay == "none") {
1871
this.iframe.style.display = "none";
1876
this.iframe.style.display = "none";
1878
this.showEvent.unsubscribe(this.showIframe, this);
1879
this.hideEvent.unsubscribe(this.hideIframe, this);
1885
* The default event handler fired when the "constraintoviewport" property is changed.
1886
* @method configConstrainToViewport
1887
* @param {String} type The CustomEvent type (usually the property name)
1888
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1889
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
1891
YAHOO.widget.Overlay.prototype.configConstrainToViewport = function(type, args, obj) {
1894
if (! YAHOO.util.Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
1895
this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
1898
this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
1903
* The default event handler fired when the "context" property is changed.
1904
* @method configContext
1905
* @param {String} type The CustomEvent type (usually the property name)
1906
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1907
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
1909
YAHOO.widget.Overlay.prototype.configContext = function(type, args, obj) {
1910
var contextArgs = args[0];
1913
var contextEl = contextArgs[0];
1914
var elementMagnetCorner = contextArgs[1];
1915
var contextMagnetCorner = contextArgs[2];
1918
if (typeof contextEl == "string") {
1919
this.cfg.setProperty("context", [document.getElementById(contextEl),elementMagnetCorner,contextMagnetCorner], true);
1922
if (elementMagnetCorner && contextMagnetCorner) {
1923
this.align(elementMagnetCorner, contextMagnetCorner);
1930
// END BUILT-IN PROPERTY EVENT HANDLERS //
1933
* Aligns the Overlay to its context element using the specified corner points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, and BOTTOM_RIGHT.
1935
* @param {String} elementAlign The String representing the corner of the Overlay that should be aligned to the context element
1936
* @param {String} contextAlign The corner of the context element that the elementAlign corner should stick to.
1938
YAHOO.widget.Overlay.prototype.align = function(elementAlign, contextAlign) {
1939
var contextArgs = this.cfg.getProperty("context");
1941
var context = contextArgs[0];
1943
var element = this.element;
1946
if (! elementAlign) {
1947
elementAlign = contextArgs[1];
1950
if (! contextAlign) {
1951
contextAlign = contextArgs[2];
1954
if (element && context) {
1955
var elementRegion = YAHOO.util.Dom.getRegion(element);
1956
var contextRegion = YAHOO.util.Dom.getRegion(context);
1958
var doAlign = function(v,h) {
1959
switch (elementAlign) {
1960
case YAHOO.widget.Overlay.TOP_LEFT:
1963
case YAHOO.widget.Overlay.TOP_RIGHT:
1964
me.moveTo(h-element.offsetWidth,v);
1966
case YAHOO.widget.Overlay.BOTTOM_LEFT:
1967
me.moveTo(h,v-element.offsetHeight);
1969
case YAHOO.widget.Overlay.BOTTOM_RIGHT:
1970
me.moveTo(h-element.offsetWidth,v-element.offsetHeight);
1975
switch (contextAlign) {
1976
case YAHOO.widget.Overlay.TOP_LEFT:
1977
doAlign(contextRegion.top, contextRegion.left);
1979
case YAHOO.widget.Overlay.TOP_RIGHT:
1980
doAlign(contextRegion.top, contextRegion.right);
1982
case YAHOO.widget.Overlay.BOTTOM_LEFT:
1983
doAlign(contextRegion.bottom, contextRegion.left);
1985
case YAHOO.widget.Overlay.BOTTOM_RIGHT:
1986
doAlign(contextRegion.bottom, contextRegion.right);
1994
* The default event handler executed when the moveEvent is fired, if the "constraintoviewport" is set to true.
1995
* @method enforceConstraints
1996
* @param {String} type The CustomEvent type (usually the property name)
1997
* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1998
* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner.
2000
YAHOO.widget.Overlay.prototype.enforceConstraints = function(type, args, obj) {
2006
var offsetHeight = this.element.offsetHeight;
2007
var offsetWidth = this.element.offsetWidth;
2009
var viewPortWidth = YAHOO.util.Dom.getViewportWidth();
2010
var viewPortHeight = YAHOO.util.Dom.getViewportHeight();
2012
var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
2013
var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
2015
var topConstraint = scrollY + 10;
2016
var leftConstraint = scrollX + 10;
2017
var bottomConstraint = scrollY + viewPortHeight - offsetHeight - 10;
2018
var rightConstraint = scrollX + viewPortWidth - offsetWidth - 10;
2020
if (x < leftConstraint) {
2022
} else if (x > rightConstraint) {
2023
x = rightConstraint;
2026
if (y < topConstraint) {
2028
} else if (y > bottomConstraint) {
2029
y = bottomConstraint;
2032
this.cfg.setProperty("x", x, true);
2033
this.cfg.setProperty("y", y, true);
2034
this.cfg.setProperty("xy", [x,y], true);
2038
* Centers the container in the viewport.
2041
YAHOO.widget.Overlay.prototype.center = function() {
2042
var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
2043
var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
2045
var viewPortWidth = YAHOO.util.Dom.getClientWidth();
2046
var viewPortHeight = YAHOO.util.Dom.getClientHeight();
2048
var elementWidth = this.element.offsetWidth;
2049
var elementHeight = this.element.offsetHeight;
2051
var x = (viewPortWidth / 2) - (elementWidth / 2) + scrollX;
2052
var y = (viewPortHeight / 2) - (elementHeight / 2) + scrollY;
2054
this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
2056
this.cfg.refireEvent("iframe");
2060
* Synchronizes the Panel's "xy", "x", and "y" properties with the Panel's position in the DOM. This is primarily used to update position information during drag & drop.
2061
* @method syncPosition
2063
YAHOO.widget.Overlay.prototype.syncPosition = function() {
2064
var pos = YAHOO.util.Dom.getXY(this.element);
2065
this.cfg.setProperty("x", pos[0], true);
2066
this.cfg.setProperty("y", pos[1], true);
2067
this.cfg.setProperty("xy", pos, true);
2071
* Event handler fired when the resize monitor element is resized.
2072
* @method onDomResize
2073
* @param {DOMEvent} e The resize DOM event
2074
* @param {Object} obj The scope object
2076
YAHOO.widget.Overlay.prototype.onDomResize = function(e, obj) {
2077
YAHOO.widget.Overlay.superclass.onDomResize.call(this, e, obj);
2079
setTimeout(function() {
2081
me.cfg.refireEvent("iframe");
2082
me.cfg.refireEvent("context");
2087
* Removes the Overlay element from the DOM and sets all child elements to null.
2090
YAHOO.widget.Overlay.prototype.destroy = function() {
2092
this.iframe.parentNode.removeChild(this.iframe);
2097
YAHOO.widget.Overlay.windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2098
YAHOO.widget.Overlay.windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2100
YAHOO.widget.Overlay.superclass.destroy.call(this);
2104
* Returns a String representation of the object.
2106
* @return {String} The string representation of the Overlay.
2108
YAHOO.widget.Overlay.prototype.toString = function() {
2109
return "Overlay " + this.id;
2113
* A singleton CustomEvent used for reacting to the DOM event for window scroll
2114
* @event YAHOO.widget.Overlay.windowScrollEvent
2116
YAHOO.widget.Overlay.windowScrollEvent = new YAHOO.util.CustomEvent("windowScroll");
2119
* A singleton CustomEvent used for reacting to the DOM event for window resize
2120
* @event YAHOO.widget.Overlay.windowResizeEvent
2122
YAHOO.widget.Overlay.windowResizeEvent = new YAHOO.util.CustomEvent("windowResize");
2125
* The DOM event handler used to fire the CustomEvent for window scroll
2126
* @method YAHOO.widget.Overlay.windowScrollHandler
2128
* @param {DOMEvent} e The DOM scroll event
2130
YAHOO.widget.Overlay.windowScrollHandler = function(e) {
2131
if (YAHOO.widget.Module.prototype.browser == "ie" || YAHOO.widget.Module.prototype.browser == "ie7") {
2132
if (! window.scrollEnd) {
2133
window.scrollEnd = -1;
2135
clearTimeout(window.scrollEnd);
2136
window.scrollEnd = setTimeout(function() { YAHOO.widget.Overlay.windowScrollEvent.fire(); }, 1);
2138
YAHOO.widget.Overlay.windowScrollEvent.fire();
2143
* The DOM event handler used to fire the CustomEvent for window resize
2144
* @method YAHOO.widget.Overlay.windowResizeHandler
2146
* @param {DOMEvent} e The DOM resize event
2148
YAHOO.widget.Overlay.windowResizeHandler = function(e) {
2149
if (YAHOO.widget.Module.prototype.browser == "ie" || YAHOO.widget.Module.prototype.browser == "ie7") {
2150
if (! window.resizeEnd) {
2151
window.resizeEnd = -1;
2153
clearTimeout(window.resizeEnd);
2154
window.resizeEnd = setTimeout(function() { YAHOO.widget.Overlay.windowResizeEvent.fire(); }, 100);
2156
YAHOO.widget.Overlay.windowResizeEvent.fire();
2161
* A boolean that indicated whether the window resize and scroll events have already been subscribed to.
2162
* @property YAHOO.widget.Overlay._initialized
2166
YAHOO.widget.Overlay._initialized = null;
2168
if (YAHOO.widget.Overlay._initialized === null) {
2169
YAHOO.util.Event.addListener(window, "scroll", YAHOO.widget.Overlay.windowScrollHandler);
2170
YAHOO.util.Event.addListener(window, "resize", YAHOO.widget.Overlay.windowResizeHandler);
2172
YAHOO.widget.Overlay._initialized = true;
2176
* OverlayManager is used for maintaining the focus status of multiple Overlays.* @namespace YAHOO.widget
2177
* @namespace YAHOO.widget
2178
* @class OverlayManager
2180
* @param {Array} overlays Optional. A collection of Overlays to register with the manager.
2181
* @param {Object} userConfig The object literal representing the user configuration of the OverlayManager
2183
YAHOO.widget.OverlayManager = function(userConfig) {
2184
this.init(userConfig);
2188
* The CSS class representing a focused Overlay
2189
* @property YAHOO.widget.OverlayManager.CSS_FOCUSED
2194
YAHOO.widget.OverlayManager.CSS_FOCUSED = "focused";
2196
YAHOO.widget.OverlayManager.prototype = {
2198
* The class's constructor function
2199
* @property contructor
2202
constructor : YAHOO.widget.OverlayManager,
2205
* The array of Overlays that are currently registered
2206
* @property overlays
2207
* @type YAHOO.widget.Overlay[]
2212
* Initializes the default configuration of the OverlayManager
2213
* @method initDefaultConfig
2215
initDefaultConfig : function() {
2217
* The collection of registered Overlays in use by the OverlayManager
2219
* @type YAHOO.widget.Overlay[]
2222
this.cfg.addProperty("overlays", { suppressEvent:true } );
2225
* The default DOM event that should be used to focus an Overlay
2226
* @config focusevent
2228
* @default "mousedown"
2230
this.cfg.addProperty("focusevent", { value:"mousedown" } );
2234
* Initializes the OverlayManager
2236
* @param {YAHOO.widget.Overlay[]} overlays Optional. A collection of Overlays to register with the manager.
2237
* @param {Object} userConfig The object literal representing the user configuration of the OverlayManager
2239
init : function(userConfig) {
2241
* The OverlayManager's Config object used for monitoring configuration properties.
2243
* @type YAHOO.util.Config
2245
this.cfg = new YAHOO.util.Config(this);
2247
this.initDefaultConfig();
2250
this.cfg.applyConfig(userConfig, true);
2252
this.cfg.fireQueue();
2255
* The currently activated Overlay
2256
* @property activeOverlay
2258
* @type YAHOO.widget.Overlay
2260
var activeOverlay = null;
2263
* Returns the currently focused Overlay
2265
* @return {YAHOO.widget.Overlay} The currently focused Overlay
2267
this.getActive = function() {
2268
return activeOverlay;
2272
* Focuses the specified Overlay
2274
* @param {YAHOO.widget.Overlay} overlay The Overlay to focus
2275
* @param {String} overlay The id of the Overlay to focus
2277
this.focus = function(overlay) {
2278
var o = this.find(overlay);
2282
YAHOO.util.Dom.addClass(activeOverlay.element, YAHOO.widget.OverlayManager.CSS_FOCUSED);
2283
this.overlays.sort(this.compareZIndexDesc);
2284
var topZIndex = YAHOO.util.Dom.getStyle(this.overlays[0].element, "zIndex");
2285
if (! isNaN(topZIndex) && this.overlays[0] != overlay) {
2286
activeOverlay.cfg.setProperty("zIndex", (parseInt(topZIndex, 10) + 2));
2288
this.overlays.sort(this.compareZIndexDesc);
2293
* Removes the specified Overlay from the manager
2295
* @param {YAHOO.widget.Overlay} overlay The Overlay to remove
2296
* @param {String} overlay The id of the Overlay to remove
2298
this.remove = function(overlay) {
2299
var o = this.find(overlay);
2301
var originalZ = YAHOO.util.Dom.getStyle(o.element, "zIndex");
2302
o.cfg.setProperty("zIndex", -1000, true);
2303
this.overlays.sort(this.compareZIndexDesc);
2304
this.overlays = this.overlays.slice(0, this.overlays.length-1);
2305
o.cfg.setProperty("zIndex", originalZ, true);
2307
o.cfg.setProperty("manager", null);
2308
o.focusEvent = null;
2316
* Removes focus from all registered Overlays in the manager
2319
this.blurAll = function() {
2320
activeOverlay = null;
2321
for (var o=0;o<this.overlays.length;o++) {
2322
YAHOO.util.Dom.removeClass(this.overlays[o].element, YAHOO.widget.OverlayManager.CSS_FOCUSED);
2326
var overlays = this.cfg.getProperty("overlays");
2328
if (! this.overlays) {
2333
this.register(overlays);
2334
this.overlays.sort(this.compareZIndexDesc);
2339
* Registers an Overlay or an array of Overlays with the manager. Upon registration, the Overlay receives functions for focus and blur, along with CustomEvents for each.
2341
* @param {YAHOO.widget.Overlay} overlay An Overlay to register with the manager.
2342
* @param {YAHOO.widget.Overlay[]} overlay An array of Overlays to register with the manager.
2343
* @return {Boolean} True if any Overlays are registered.
2345
register : function(overlay) {
2346
if (overlay instanceof YAHOO.widget.Overlay) {
2347
overlay.cfg.addProperty("manager", { value:this } );
2349
overlay.focusEvent = new YAHOO.util.CustomEvent("focus");
2350
overlay.blurEvent = new YAHOO.util.CustomEvent("blur");
2354
overlay.focus = function() {
2356
this.focusEvent.fire();
2359
overlay.blur = function() {
2361
this.blurEvent.fire();
2364
var focusOnDomEvent = function(e,obj) {
2368
var focusevent = this.cfg.getProperty("focusevent");
2369
YAHOO.util.Event.addListener(overlay.element,focusevent,focusOnDomEvent,this,true);
2371
var zIndex = YAHOO.util.Dom.getStyle(overlay.element, "zIndex");
2372
if (! isNaN(zIndex)) {
2373
overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
2375
overlay.cfg.setProperty("zIndex", 0);
2378
this.overlays.push(overlay);
2380
} else if (overlay instanceof Array) {
2382
for (var i=0;i<overlay.length;i++) {
2383
if (this.register(overlay[i])) {
2396
* Attempts to locate an Overlay by instance or ID.
2398
* @param {YAHOO.widget.Overlay} overlay An Overlay to locate within the manager
2399
* @param {String} overlay An Overlay id to locate within the manager
2400
* @return {YAHOO.widget.Overlay} The requested Overlay, if found, or null if it cannot be located.
2402
find : function(overlay) {
2403
if (overlay instanceof YAHOO.widget.Overlay) {
2404
for (var o=0;o<this.overlays.length;o++) {
2405
if (this.overlays[o] == overlay) {
2406
return this.overlays[o];
2409
} else if (typeof overlay == "string") {
2410
for (var p=0;p<this.overlays.length;p++) {
2411
if (this.overlays[p].id == overlay) {
2412
return this.overlays[p];
2420
* Used for sorting the manager's Overlays by z-index.
2421
* @method compareZIndexDesc
2423
* @return {Number} 0, 1, or -1, depending on where the Overlay should fall in the stacking order.
2425
compareZIndexDesc : function(o1, o2) {
2426
var zIndex1 = o1.cfg.getProperty("zIndex");
2427
var zIndex2 = o2.cfg.getProperty("zIndex");
2429
if (zIndex1 > zIndex2) {
2431
} else if (zIndex1 < zIndex2) {
2439
* Shows all Overlays in the manager.
2442
showAll : function() {
2443
for (var o=0;o<this.overlays.length;o++) {
2444
this.overlays[o].show();
2449
* Hides all Overlays in the manager.
2452
hideAll : function() {
2453
for (var o=0;o<this.overlays.length;o++) {
2454
this.overlays[o].hide();
2459
* Returns a string representation of the object.
2461
* @return {String} The string representation of the OverlayManager
2463
toString : function() {
2464
return "OverlayManager";
2470
* KeyListener is a utility that provides an easy interface for listening for keydown/keyup events fired against DOM elements.
2471
* @namespace YAHOO.util
2472
* @class KeyListener
2474
* @param {HTMLElement} attachTo The element or element ID to which the key event should be attached
2475
* @param {String} attachTo The element or element ID to which the key event should be attached
2476
* @param {Object} keyData The object literal representing the key(s) to detect. Possible attributes are shift(boolean), alt(boolean), ctrl(boolean) and keys(either an int or an array of ints representing keycodes).
2477
* @param {Function} handler The CustomEvent handler to fire when the key event is detected
2478
* @param {Object} handler An object literal representing the handler.
2479
* @param {String} event Optional. The event (keydown or keyup) to listen for. Defaults automatically to keydown.
2481
YAHOO.util.KeyListener = function(attachTo, keyData, handler, event) {
2483
YAHOO.log("No attachTo element specified", "error");
2486
YAHOO.log("No keyData specified", "error");
2489
YAHOO.log("No handler specified", "error");
2493
event = YAHOO.util.KeyListener.KEYDOWN;
2497
* The CustomEvent fired internally when a key is pressed
2500
* @param {Object} keyData The object literal representing the key(s) to detect. Possible attributes are shift(boolean), alt(boolean), ctrl(boolean) and keys(either an int or an array of ints representing keycodes).
2502
var keyEvent = new YAHOO.util.CustomEvent("keyPressed");
2505
* The CustomEvent fired when the KeyListener is enabled via the enable() function
2506
* @event enabledEvent
2507
* @param {Object} keyData The object literal representing the key(s) to detect. Possible attributes are shift(boolean), alt(boolean), ctrl(boolean) and keys(either an int or an array of ints representing keycodes).
2509
this.enabledEvent = new YAHOO.util.CustomEvent("enabled");
2512
* The CustomEvent fired when the KeyListener is disabled via the disable() function
2513
* @event disabledEvent
2514
* @param {Object} keyData The object literal representing the key(s) to detect. Possible attributes are shift(boolean), alt(boolean), ctrl(boolean) and keys(either an int or an array of ints representing keycodes).
2516
this.disabledEvent = new YAHOO.util.CustomEvent("disabled");
2518
if (typeof attachTo == 'string') {
2519
attachTo = document.getElementById(attachTo);
2522
if (typeof handler == 'function') {
2523
keyEvent.subscribe(handler);
2525
keyEvent.subscribe(handler.fn, handler.scope, handler.correctScope);
2529
* Handles the key event when a key is pressed.
2530
* @method handleKeyPress
2531
* @param {DOMEvent} e The keypress DOM event
2532
* @param {Object} obj The DOM event scope object
2535
function handleKeyPress(e, obj) {
2536
if (! keyData.shift) {
2537
keyData.shift = false;
2539
if (! keyData.alt) {
2540
keyData.alt = false;
2542
if (! keyData.ctrl) {
2543
keyData.ctrl = false;
2546
// check held down modifying keys first
2547
if (e.shiftKey == keyData.shift &&
2548
e.altKey == keyData.alt &&
2549
e.ctrlKey == keyData.ctrl) { // if we pass this, all modifiers match
2554
if (keyData.keys instanceof Array) {
2555
for (var i=0;i<keyData.keys.length;i++) {
2556
dataItem = keyData.keys[i];
2558
if (dataItem == e.charCode ) {
2559
keyEvent.fire(e.charCode, e);
2561
} else if (dataItem == e.keyCode) {
2562
keyEvent.fire(e.keyCode, e);
2567
dataItem = keyData.keys;
2568
if (dataItem == e.charCode ) {
2569
keyEvent.fire(e.charCode, e);
2570
} else if (dataItem == e.keyCode) {
2571
keyEvent.fire(e.keyCode, e);
2578
* Enables the KeyListener by attaching the DOM event listeners to the target DOM element
2581
this.enable = function() {
2582
if (! this.enabled) {
2583
YAHOO.util.Event.addListener(attachTo, event, handleKeyPress);
2584
this.enabledEvent.fire(keyData);
2587
* Boolean indicating the enabled/disabled state of the Tooltip
2591
this.enabled = true;
2595
* Disables the KeyListener by removing the DOM event listeners from the target DOM element
2598
this.disable = function() {
2600
YAHOO.util.Event.removeListener(attachTo, event, handleKeyPress);
2601
this.disabledEvent.fire(keyData);
2603
this.enabled = false;
2607
* Returns a String representation of the object.
2609
* @return {String} The string representation of the KeyListener
2611
this.toString = function() {
2612
return "KeyListener [" + keyData.keys + "] " + attachTo.tagName + (attachTo.id ? "[" + attachTo.id + "]" : "");
2618
* Constant representing the DOM "keydown" event.
2619
* @property YAHOO.util.KeyListener.KEYDOWN
2624
YAHOO.util.KeyListener.KEYDOWN = "keydown";
2627
* Constant representing the DOM "keyup" event.
2628
* @property YAHOO.util.KeyListener.KEYUP
2633
YAHOO.util.KeyListener.KEYUP = "keyup";
2636
* ContainerEffect encapsulates animation transitions that are executed when an Overlay is shown or hidden.
2637
* @namespace YAHOO.widget
2638
* @class ContainerEffect
2640
* @param {YAHOO.widget.Overlay} overlay The Overlay that the animation should be associated with
2641
* @param {Object} attrIn The object literal representing the animation arguments to be used for the animate-in transition. The arguments for this literal are: attributes(object, see YAHOO.util.Anim for description), duration(Number), and method(i.e. YAHOO.util.Easing.easeIn).
2642
* @param {Object} attrOut The object literal representing the animation arguments to be used for the animate-out transition. The arguments for this literal are: attributes(object, see YAHOO.util.Anim for description), duration(Number), and method(i.e. YAHOO.util.Easing.easeIn).
2643
* @param {HTMLElement} targetElement Optional. The target element that should be animated during the transition. Defaults to overlay.element.
2644
* @param {class} Optional. The animation class to instantiate. Defaults to YAHOO.util.Anim. Other options include YAHOO.util.Motion.
2646
YAHOO.widget.ContainerEffect = function(overlay, attrIn, attrOut, targetElement, animClass) {
2648
animClass = YAHOO.util.Anim;
2652
* The overlay to animate
2654
* @type YAHOO.widget.Overlay
2656
this.overlay = overlay;
2658
* The animation attributes to use when transitioning into view
2662
this.attrIn = attrIn;
2664
* The animation attributes to use when transitioning out of view
2668
this.attrOut = attrOut;
2670
* The target element to be animated
2671
* @property targetElement
2674
this.targetElement = targetElement || overlay.element;
2676
* The animation class to use for animating the overlay
2677
* @property animClass
2680
this.animClass = animClass;
2684
* Initializes the animation classes and events.
2687
YAHOO.widget.ContainerEffect.prototype.init = function() {
2688
this.beforeAnimateInEvent = new YAHOO.util.CustomEvent("beforeAnimateIn");
2689
this.beforeAnimateOutEvent = new YAHOO.util.CustomEvent("beforeAnimateOut");
2691
this.animateInCompleteEvent = new YAHOO.util.CustomEvent("animateInComplete");
2692
this.animateOutCompleteEvent = new YAHOO.util.CustomEvent("animateOutComplete");
2694
this.animIn = new this.animClass(this.targetElement, this.attrIn.attributes, this.attrIn.duration, this.attrIn.method);
2695
this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
2696
this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
2697
this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn, this);
2699
this.animOut = new this.animClass(this.targetElement, this.attrOut.attributes, this.attrOut.duration, this.attrOut.method);
2700
this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
2701
this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
2702
this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut, this);
2706
* Triggers the in-animation.
2709
YAHOO.widget.ContainerEffect.prototype.animateIn = function() {
2710
this.beforeAnimateInEvent.fire();
2711
this.animIn.animate();
2715
* Triggers the out-animation.
2716
* @method animateOut
2718
YAHOO.widget.ContainerEffect.prototype.animateOut = function() {
2719
this.beforeAnimateOutEvent.fire();
2720
this.animOut.animate();
2724
* The default onStart handler for the in-animation.
2725
* @method handleStartAnimateIn
2726
* @param {String} type The CustomEvent type
2727
* @param {Object[]} args The CustomEvent arguments
2728
* @param {Object} obj The scope object
2730
YAHOO.widget.ContainerEffect.prototype.handleStartAnimateIn = function(type, args, obj) { };
2732
* The default onTween handler for the in-animation.
2733
* @method handleTweenAnimateIn
2734
* @param {String} type The CustomEvent type
2735
* @param {Object[]} args The CustomEvent arguments
2736
* @param {Object} obj The scope object
2738
YAHOO.widget.ContainerEffect.prototype.handleTweenAnimateIn = function(type, args, obj) { };
2740
* The default onComplete handler for the in-animation.
2741
* @method handleCompleteAnimateIn
2742
* @param {String} type The CustomEvent type
2743
* @param {Object[]} args The CustomEvent arguments
2744
* @param {Object} obj The scope object
2746
YAHOO.widget.ContainerEffect.prototype.handleCompleteAnimateIn = function(type, args, obj) { };
2749
* The default onStart handler for the out-animation.
2750
* @method handleStartAnimateOut
2751
* @param {String} type The CustomEvent type
2752
* @param {Object[]} args The CustomEvent arguments
2753
* @param {Object} obj The scope object
2755
YAHOO.widget.ContainerEffect.prototype.handleStartAnimateOut = function(type, args, obj) { };
2757
* The default onTween handler for the out-animation.
2758
* @method handleTweenAnimateOut
2759
* @param {String} type The CustomEvent type
2760
* @param {Object[]} args The CustomEvent arguments
2761
* @param {Object} obj The scope object
2763
YAHOO.widget.ContainerEffect.prototype.handleTweenAnimateOut = function(type, args, obj) { };
2765
* The default onComplete handler for the out-animation.
2766
* @method handleCompleteAnimateOut
2767
* @param {String} type The CustomEvent type
2768
* @param {Object[]} args The CustomEvent arguments
2769
* @param {Object} obj The scope object
2771
YAHOO.widget.ContainerEffect.prototype.handleCompleteAnimateOut = function(type, args, obj) { };
2774
* Returns a string representation of the object.
2776
* @return {String} The string representation of the ContainerEffect
2778
YAHOO.widget.ContainerEffect.prototype.toString = function() {
2779
var output = "ContainerEffect";
2781
output += " [" + this.overlay.toString() + "]";
2787
* A pre-configured ContainerEffect instance that can be used for fading an overlay in and out.
2790
* @param {Overlay} overlay The Overlay object to animate
2791
* @param {Number} dur The duration of the animation
2792
* @return {ContainerEffect} The configured ContainerEffect object
2794
YAHOO.widget.ContainerEffect.FADE = function(overlay, dur) {
2795
var fade = new YAHOO.widget.ContainerEffect(overlay, { attributes:{opacity: {from:0, to:1}}, duration:dur, method:YAHOO.util.Easing.easeIn }, { attributes:{opacity: {to:0}}, duration:dur, method:YAHOO.util.Easing.easeOut}, overlay.element );
2797
fade.handleStartAnimateIn = function(type,args,obj) {
2798
YAHOO.util.Dom.addClass(obj.overlay.element, "hide-select");
2800
if (! obj.overlay.underlay) {
2801
obj.overlay.cfg.refireEvent("underlay");
2804
if (obj.overlay.underlay) {
2805
obj.initialUnderlayOpacity = YAHOO.util.Dom.getStyle(obj.overlay.underlay, "opacity");
2806
obj.overlay.underlay.style.filter = null;
2809
YAHOO.util.Dom.setStyle(obj.overlay.element, "visibility", "visible");
2810
YAHOO.util.Dom.setStyle(obj.overlay.element, "opacity", 0);
2813
fade.handleCompleteAnimateIn = function(type,args,obj) {
2814
YAHOO.util.Dom.removeClass(obj.overlay.element, "hide-select");
2816
if (obj.overlay.element.style.filter) {
2817
obj.overlay.element.style.filter = null;
2820
if (obj.overlay.underlay) {
2821
YAHOO.util.Dom.setStyle(obj.overlay.underlay, "opacity", obj.initialUnderlayOpacity);
2824
obj.overlay.cfg.refireEvent("iframe");
2825
obj.animateInCompleteEvent.fire();
2828
fade.handleStartAnimateOut = function(type, args, obj) {
2829
YAHOO.util.Dom.addClass(obj.overlay.element, "hide-select");
2831
if (obj.overlay.underlay) {
2832
obj.overlay.underlay.style.filter = null;
2836
fade.handleCompleteAnimateOut = function(type, args, obj) {
2837
YAHOO.util.Dom.removeClass(obj.overlay.element, "hide-select");
2838
if (obj.overlay.element.style.filter) {
2839
obj.overlay.element.style.filter = null;
2841
YAHOO.util.Dom.setStyle(obj.overlay.element, "visibility", "hidden");
2842
YAHOO.util.Dom.setStyle(obj.overlay.element, "opacity", 1);
2844
obj.overlay.cfg.refireEvent("iframe");
2846
obj.animateOutCompleteEvent.fire();
2855
* A pre-configured ContainerEffect instance that can be used for sliding an overlay in and out.
2858
* @param {Overlay} overlay The Overlay object to animate
2859
* @param {Number} dur The duration of the animation
2860
* @return {ContainerEffect} The configured ContainerEffect object
2862
YAHOO.widget.ContainerEffect.SLIDE = function(overlay, dur) {
2863
var x = overlay.cfg.getProperty("x") || YAHOO.util.Dom.getX(overlay.element);
2864
var y = overlay.cfg.getProperty("y") || YAHOO.util.Dom.getY(overlay.element);
2866
var clientWidth = YAHOO.util.Dom.getClientWidth();
2867
var offsetWidth = overlay.element.offsetWidth;
2869
var slide = new YAHOO.widget.ContainerEffect(overlay, {
2870
attributes:{ points: { to:[x, y] } },
2872
method:YAHOO.util.Easing.easeIn
2875
attributes:{ points: { to:[(clientWidth+25), y] } },
2877
method:YAHOO.util.Easing.easeOut
2883
slide.handleStartAnimateIn = function(type,args,obj) {
2884
obj.overlay.element.style.left = (-25-offsetWidth) + "px";
2885
obj.overlay.element.style.top = y + "px";
2888
slide.handleTweenAnimateIn = function(type, args, obj) {
2891
var pos = YAHOO.util.Dom.getXY(obj.overlay.element);
2893
var currentX = pos[0];
2894
var currentY = pos[1];
2896
if (YAHOO.util.Dom.getStyle(obj.overlay.element, "visibility") == "hidden" && currentX < x) {
2897
YAHOO.util.Dom.setStyle(obj.overlay.element, "visibility", "visible");
2900
obj.overlay.cfg.setProperty("xy", [currentX,currentY], true);
2901
obj.overlay.cfg.refireEvent("iframe");
2904
slide.handleCompleteAnimateIn = function(type, args, obj) {
2905
obj.overlay.cfg.setProperty("xy", [x,y], true);
2908
obj.overlay.cfg.refireEvent("iframe");
2909
obj.animateInCompleteEvent.fire();
2912
slide.handleStartAnimateOut = function(type, args, obj) {
2913
var vw = YAHOO.util.Dom.getViewportWidth();
2915
var pos = YAHOO.util.Dom.getXY(obj.overlay.element);
2919
var currentTo = obj.animOut.attributes.points.to;
2920
obj.animOut.attributes.points.to = [(vw+25), yso];
2923
slide.handleTweenAnimateOut = function(type, args, obj) {
2924
var pos = YAHOO.util.Dom.getXY(obj.overlay.element);
2929
obj.overlay.cfg.setProperty("xy", [xto,yto], true);
2930
obj.overlay.cfg.refireEvent("iframe");
2933
slide.handleCompleteAnimateOut = function(type, args, obj) {
2934
YAHOO.util.Dom.setStyle(obj.overlay.element, "visibility", "hidden");
2936
obj.overlay.cfg.setProperty("xy", [x,y]);
2937
obj.animateOutCompleteEvent.fire();
b'\\ No newline at end of file'
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) {
26
if (!owner) { YAHOO.log("No owner specified for Config object", "error", "Config"); }
31
var Lang = YAHOO.lang,
32
CustomEvent = YAHOO.util.CustomEvent,
33
Config = YAHOO.util.Config;
37
* Constant representing the CustomEvent type for the config changed event.
38
* @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
43
Config.CONFIG_CHANGED_EVENT = "configChanged";
46
* Constant representing the boolean type string
47
* @property YAHOO.util.Config.BOOLEAN_TYPE
52
Config.BOOLEAN_TYPE = "boolean";
57
* Object reference to the owner of this Config Object
64
* Boolean flag that specifies whether a queue is currently
66
* @property queueInProgress
69
queueInProgress: false,
72
* Maintains the local collection of configuration property objects and
73
* their specified values
81
* Maintains the local collection of configuration property objects as
82
* they were initially applied.
83
* This object is used when resetting a property.
84
* @property initialConfig
91
* Maintains the local, normalized CustomEvent queue
92
* @property eventQueue
99
* Custom Event, notifying subscribers when Config properties are set
100
* (setProperty is called without the silent flag
101
* @event configChangedEvent
103
configChangedEvent: null,
106
* Initializes the configuration Object and all of its local members.
108
* @param {Object} owner The owner Object to which this Config
111
init: function (owner) {
115
this.configChangedEvent =
116
this.createEvent(Config.CONFIG_CHANGED_EVENT);
118
this.configChangedEvent.signature = CustomEvent.LIST;
119
this.queueInProgress = false;
121
this.initialConfig = {};
122
this.eventQueue = [];
127
* Validates that the value passed in is a Boolean.
128
* @method checkBoolean
129
* @param {Object} val The value to validate
130
* @return {Boolean} true, if the value is valid
132
checkBoolean: function (val) {
133
return (typeof val == Config.BOOLEAN_TYPE);
137
* Validates that the value passed in is a number.
138
* @method checkNumber
139
* @param {Object} val The value to validate
140
* @return {Boolean} true, if the value is valid
142
checkNumber: function (val) {
143
return (!isNaN(val));
147
* Fires a configuration property event using the specified value.
150
* @param {String} key The configuration property's name
151
* @param {value} Object The value of the correct type for the property
153
fireEvent: function ( key, value ) {
154
YAHOO.log("Firing Config event: " + key + "=" + value, "info", "Config");
155
var property = this.config[key];
157
if (property && property.event) {
158
property.event.fire(value);
163
* Adds a property to the Config Object's private config hash.
164
* @method addProperty
165
* @param {String} key The configuration property's name
166
* @param {Object} propertyObject The Object containing all of this
167
* property's arguments
169
addProperty: function ( key, propertyObject ) {
170
key = key.toLowerCase();
171
YAHOO.log("Added property: " + key, "info", "Config");
173
this.config[key] = propertyObject;
175
propertyObject.event = this.createEvent(key, { scope: this.owner });
176
propertyObject.event.signature = CustomEvent.LIST;
179
propertyObject.key = key;
181
if (propertyObject.handler) {
182
propertyObject.event.subscribe(propertyObject.handler,
186
this.setProperty(key, propertyObject.value, true);
188
if (! propertyObject.suppressEvent) {
189
this.queueProperty(key, propertyObject.value);
195
* Returns a key-value configuration map of the values currently set in
198
* @return {Object} The current config, represented in a key-value map
200
getConfig: function () {
203
currCfg = this.config,
207
for (prop in currCfg) {
208
if (Lang.hasOwnProperty(currCfg, prop)) {
209
property = currCfg[prop];
210
if (property && property.event) {
211
cfg[prop] = property.value;
220
* Returns the value of specified property.
221
* @method getProperty
222
* @param {String} key The name of the property
223
* @return {Object} The value of the specified property
225
getProperty: function (key) {
226
var property = this.config[key.toLowerCase()];
227
if (property && property.event) {
228
return property.value;
235
* Resets the specified property's value to its initial value.
236
* @method resetProperty
237
* @param {String} key The name of the property
238
* @return {Boolean} True is the property was reset, false if not
240
resetProperty: function (key) {
242
key = key.toLowerCase();
244
var property = this.config[key];
246
if (property && property.event) {
248
if (this.initialConfig[key] &&
249
!Lang.isUndefined(this.initialConfig[key])) {
251
this.setProperty(key, this.initialConfig[key]);
265
* Sets the value of a property. If the silent property is passed as
266
* true, the property's event will not be fired.
267
* @method setProperty
268
* @param {String} key The name of the property
269
* @param {String} value The value to set the property to
270
* @param {Boolean} silent Whether the value should be set silently,
271
* without firing the property event.
272
* @return {Boolean} True, if the set was successful, false if it failed.
274
setProperty: function (key, value, silent) {
278
key = key.toLowerCase();
279
YAHOO.log("setProperty: " + key + "=" + value, "info", "Config");
281
if (this.queueInProgress && ! silent) {
282
// Currently running through a queue...
283
this.queueProperty(key,value);
287
property = this.config[key];
288
if (property && property.event) {
289
if (property.validator && !property.validator(value)) {
292
property.value = value;
294
this.fireEvent(key, value);
295
this.configChangedEvent.fire([key, value]);
306
* Sets the value of a property and queues its event to execute. If the
307
* event is already scheduled to execute, it is
308
* moved from its current position to the end of the queue.
309
* @method queueProperty
310
* @param {String} key The name of the property
311
* @param {String} value The value to set the property to
312
* @return {Boolean} true, if the set was successful, false if
315
queueProperty: function (key, value) {
317
key = key.toLowerCase();
318
YAHOO.log("queueProperty: " + key + "=" + value, "info", "Config");
320
var property = this.config[key],
321
foundDuplicate = false,
336
if (property && property.event) {
338
if (!Lang.isUndefined(value) && property.validator &&
339
!property.validator(value)) { // validator
343
if (!Lang.isUndefined(value)) {
344
property.value = value;
346
value = property.value;
349
foundDuplicate = false;
350
iLen = this.eventQueue.length;
352
for (i = 0; i < iLen; i++) {
353
queueItem = this.eventQueue[i];
356
queueItemKey = queueItem[0];
357
queueItemValue = queueItem[1];
359
if (queueItemKey == key) {
362
found a dupe... push to end of queue, null
363
current item, and break
366
this.eventQueue[i] = null;
368
this.eventQueue.push(
369
[key, (!Lang.isUndefined(value) ?
370
value : queueItemValue)]);
372
foundDuplicate = true;
378
// this is a refire, or a new property in the queue
380
if (! foundDuplicate && !Lang.isUndefined(value)) {
381
this.eventQueue.push([key, value]);
385
if (property.supercedes) {
387
sLen = property.supercedes.length;
389
for (s = 0; s < sLen; s++) {
391
supercedesCheck = property.supercedes[s];
392
qLen = this.eventQueue.length;
394
for (q = 0; q < qLen; q++) {
395
queueItemCheck = this.eventQueue[q];
397
if (queueItemCheck) {
398
queueItemCheckKey = queueItemCheck[0];
399
queueItemCheckValue = queueItemCheck[1];
401
if (queueItemCheckKey ==
402
supercedesCheck.toLowerCase() ) {
404
this.eventQueue.push([queueItemCheckKey,
405
queueItemCheckValue]);
407
this.eventQueue[q] = null;
416
YAHOO.log("Config event queue: " + this.outputEventQueue(), "info", "Config");
425
* Fires the event for a property using the property's current value.
426
* @method refireEvent
427
* @param {String} key The name of the property
429
refireEvent: function (key) {
431
key = key.toLowerCase();
433
var property = this.config[key];
435
if (property && property.event &&
437
!Lang.isUndefined(property.value)) {
439
if (this.queueInProgress) {
441
this.queueProperty(key);
445
this.fireEvent(key, property.value);
453
* Applies a key-value Object literal to the configuration, replacing
454
* any existing values, and queueing the property events.
455
* Although the values will be set, fireQueue() must be called for their
456
* associated events to execute.
457
* @method applyConfig
458
* @param {Object} userConfig The configuration Object literal
459
* @param {Boolean} init When set to true, the initialConfig will
460
* be set to the userConfig passed in, so that calling a reset will
461
* reset the properties to the passed values.
463
applyConfig: function (userConfig, init) {
470
for (sKey in userConfig) {
471
if (Lang.hasOwnProperty(userConfig, sKey)) {
472
oConfig[sKey.toLowerCase()] = userConfig[sKey];
475
this.initialConfig = oConfig;
478
for (sKey in userConfig) {
479
if (Lang.hasOwnProperty(userConfig, sKey)) {
480
this.queueProperty(sKey, userConfig[sKey]);
486
* Refires the events for all configuration properties using their
490
refresh: function () {
494
for (prop in this.config) {
495
if (Lang.hasOwnProperty(this.config, prop)) {
496
this.refireEvent(prop);
502
* Fires the normalized list of queued property change events
505
fireQueue: function () {
513
this.queueInProgress = true;
514
for (i = 0;i < this.eventQueue.length; i++) {
515
queueItem = this.eventQueue[i];
519
value = queueItem[1];
520
property = this.config[key];
522
property.value = value;
524
// Clear out queue entry, to avoid it being
525
// re-added to the queue by any queueProperty/supercedes
526
// calls which are invoked during fireEvent
527
this.eventQueue[i] = null;
529
this.fireEvent(key,value);
533
this.queueInProgress = false;
534
this.eventQueue = [];
538
* Subscribes an external handler to the change event for any
540
* @method subscribeToConfigEvent
541
* @param {String} key The property name
542
* @param {Function} handler The handler function to use subscribe to
543
* the property's event
544
* @param {Object} obj The Object to use for scoping the event handler
545
* (see CustomEvent documentation)
546
* @param {Boolean} override Optional. If true, will override "this"
547
* within the handler to map to the scope Object passed into the method.
548
* @return {Boolean} True, if the subscription was successful,
551
subscribeToConfigEvent: function (key, handler, obj, override) {
553
var property = this.config[key.toLowerCase()];
555
if (property && property.event) {
556
if (!Config.alreadySubscribed(property.event, handler, obj)) {
557
property.event.subscribe(handler, obj, override);
567
* Unsubscribes an external handler from the change event for any
569
* @method unsubscribeFromConfigEvent
570
* @param {String} key The property name
571
* @param {Function} handler The handler function to use subscribe to
572
* the property's event
573
* @param {Object} obj The Object to use for scoping the event
574
* handler (see CustomEvent documentation)
575
* @return {Boolean} True, if the unsubscription was successful,
578
unsubscribeFromConfigEvent: function (key, handler, obj) {
579
var property = this.config[key.toLowerCase()];
580
if (property && property.event) {
581
return property.event.unsubscribe(handler, obj);
588
* Returns a string representation of the Config object
590
* @return {String} The Config object in string format.
592
toString: function () {
593
var output = "Config";
595
output += " [" + this.owner.toString() + "]";
601
* Returns a string representation of the Config object's current
603
* @method outputEventQueue
604
* @return {String} The string list of CustomEvents currently queued
607
outputEventQueue: function () {
612
nQueue = this.eventQueue.length;
614
for (q = 0; q < nQueue; q++) {
615
queueItem = this.eventQueue[q];
617
output += queueItem[0] + "=" + queueItem[1] + ", ";
624
* Sets all properties to null, unsubscribes all listeners from each
625
* property's change event and all listeners from the configChangedEvent.
628
destroy: function () {
630
var oConfig = this.config,
635
for (sProperty in oConfig) {
637
if (Lang.hasOwnProperty(oConfig, sProperty)) {
639
oProperty = oConfig[sProperty];
641
oProperty.event.unsubscribeAll();
642
oProperty.event = null;
648
this.configChangedEvent.unsubscribeAll();
650
this.configChangedEvent = null;
653
this.initialConfig = null;
654
this.eventQueue = null;
663
* Checks to determine if a particular function/Object pair are already
664
* subscribed to the specified CustomEvent
665
* @method YAHOO.util.Config.alreadySubscribed
667
* @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check
669
* @param {Function} fn The function to look for in the subscribers list
670
* @param {Object} obj The execution scope Object for the subscription
671
* @return {Boolean} true, if the function/Object pair is already subscribed
672
* to the CustomEvent passed in
674
Config.alreadySubscribed = function (evt, fn, obj) {
676
var nSubscribers = evt.subscribers.length,
680
if (nSubscribers > 0) {
681
i = nSubscribers - 1;
683
subsc = evt.subscribers[i];
684
if (subsc && subsc.obj == obj && subsc.fn == fn) {
695
YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
702
* The Container family of components is designed to enable developers to
703
* create different kinds of content-containing modules on the web. Module
704
* and Overlay are the most basic containers, and they can be used directly
705
* or extended to build custom containers. Also part of the Container family
706
* are four UI controls that extend Module and Overlay: Tooltip, Panel,
707
* Dialog, and SimpleDialog.
710
* @requires yahoo, dom, event
711
* @optional dragdrop, animation, button
715
* Module is a JavaScript representation of the Standard Module Format.
716
* Standard Module Format is a simple standard for markup containers where
717
* child nodes representing the header, body, and footer of the content are
718
* denoted using the CSS classes "hd", "bd", and "ft" respectively.
719
* Module is the base class for all other classes in the YUI
721
* @namespace YAHOO.widget
724
* @param {String} el The element ID representing the Module <em>OR</em>
725
* @param {HTMLElement} el The element representing the Module
726
* @param {Object} userConfig The configuration Object literal containing
727
* the configuration that should be set for this module. See configuration
728
* documentation for more details.
730
YAHOO.widget.Module = function (el, userConfig) {
732
this.init(el, userConfig);
734
YAHOO.log("No element or element ID specified" +
735
" for Module instantiation", "error");
739
var Dom = YAHOO.util.Dom,
740
Config = YAHOO.util.Config,
741
Event = YAHOO.util.Event,
742
CustomEvent = YAHOO.util.CustomEvent,
743
Module = YAHOO.widget.Module,
751
* Constant representing the name of the Module's events
752
* @property EVENT_TYPES
758
"BEFORE_INIT": "beforeInit",
761
"BEFORE_RENDER": "beforeRender",
763
"CHANGE_HEADER": "changeHeader",
764
"CHANGE_BODY": "changeBody",
765
"CHANGE_FOOTER": "changeFooter",
766
"CHANGE_CONTENT": "changeContent",
767
"DESTORY": "destroy",
768
"BEFORE_SHOW": "beforeShow",
770
"BEFORE_HIDE": "beforeHide",
775
* Constant representing the Module's configuration properties
776
* @property DEFAULT_CONFIG
786
validator: YAHOO.lang.isBoolean
792
supercedes: ["visible"]
796
key: "monitorresize",
800
"APPEND_TO_DOCUMENT_BODY": {
801
key: "appendtodocumentbody",
807
* Constant representing the prefix path to use for non-secure images
808
* @property YAHOO.widget.Module.IMG_ROOT
813
Module.IMG_ROOT = null;
816
* Constant representing the prefix path to use for securely served images
817
* @property YAHOO.widget.Module.IMG_ROOT_SSL
822
Module.IMG_ROOT_SSL = null;
825
* Constant for the default CSS class name that represents a Module
826
* @property YAHOO.widget.Module.CSS_MODULE
831
Module.CSS_MODULE = "yui-module";
834
* Constant representing the module header
835
* @property YAHOO.widget.Module.CSS_HEADER
840
Module.CSS_HEADER = "hd";
843
* Constant representing the module body
844
* @property YAHOO.widget.Module.CSS_BODY
849
Module.CSS_BODY = "bd";
852
* Constant representing the module footer
853
* @property YAHOO.widget.Module.CSS_FOOTER
858
Module.CSS_FOOTER = "ft";
861
* Constant representing the url for the "src" attribute of the iframe
862
* used to monitor changes to the browser's base font size
863
* @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
868
Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
871
* Singleton CustomEvent fired when the font size is changed in the browser.
872
* Opera's "zoom" functionality currently does not support text
874
* @event YAHOO.widget.Module.textResizeEvent
876
Module.textResizeEvent = new CustomEvent("textResize");
878
function createModuleTemplate() {
880
if (!m_oModuleTemplate) {
881
m_oModuleTemplate = document.createElement("div");
883
m_oModuleTemplate.innerHTML = ("<div class=\"" +
884
Module.CSS_HEADER + "\"></div>" + "<div class=\"" +
885
Module.CSS_BODY + "\"></div><div class=\"" +
886
Module.CSS_FOOTER + "\"></div>");
888
m_oHeaderTemplate = m_oModuleTemplate.firstChild;
889
m_oBodyTemplate = m_oHeaderTemplate.nextSibling;
890
m_oFooterTemplate = m_oBodyTemplate.nextSibling;
893
return m_oModuleTemplate;
896
function createHeader() {
897
if (!m_oHeaderTemplate) {
898
createModuleTemplate();
900
return (m_oHeaderTemplate.cloneNode(false));
903
function createBody() {
904
if (!m_oBodyTemplate) {
905
createModuleTemplate();
907
return (m_oBodyTemplate.cloneNode(false));
910
function createFooter() {
911
if (!m_oFooterTemplate) {
912
createModuleTemplate();
914
return (m_oFooterTemplate.cloneNode(false));
920
* The class's constructor function
921
* @property contructor
927
* The main module element that contains the header, body, and footer
934
* The header element, denoted with CSS class "hd"
941
* The body element, denoted with CSS class "bd"
948
* The footer element, denoted with CSS class "ft"
955
* The id of the element
962
* A string representing the root path for all images created by
964
* @deprecated It is recommend that any images for a Module be applied
965
* via CSS using the "background-image" property.
966
* @property imageRoot
969
imageRoot: Module.IMG_ROOT,
972
* Initializes the custom events for Module which are fired
973
* automatically at appropriate times by the Module class.
976
initEvents: function () {
978
var SIGNATURE = CustomEvent.LIST;
981
* CustomEvent fired prior to class initalization.
982
* @event beforeInitEvent
983
* @param {class} classRef class reference of the initializing
984
* class, such as this.beforeInitEvent.fire(Module)
986
this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT);
987
this.beforeInitEvent.signature = SIGNATURE;
990
* CustomEvent fired after class initalization.
992
* @param {class} classRef class reference of the initializing
993
* class, such as this.beforeInitEvent.fire(Module)
995
this.initEvent = this.createEvent(EVENT_TYPES.INIT);
996
this.initEvent.signature = SIGNATURE;
999
* CustomEvent fired when the Module is appended to the DOM
1000
* @event appendEvent
1002
this.appendEvent = this.createEvent(EVENT_TYPES.APPEND);
1003
this.appendEvent.signature = SIGNATURE;
1006
* CustomEvent fired before the Module is rendered
1007
* @event beforeRenderEvent
1009
this.beforeRenderEvent = this.createEvent(EVENT_TYPES.BEFORE_RENDER);
1010
this.beforeRenderEvent.signature = SIGNATURE;
1013
* CustomEvent fired after the Module is rendered
1014
* @event renderEvent
1016
this.renderEvent = this.createEvent(EVENT_TYPES.RENDER);
1017
this.renderEvent.signature = SIGNATURE;
1020
* CustomEvent fired when the header content of the Module
1022
* @event changeHeaderEvent
1023
* @param {String/HTMLElement} content String/element representing
1024
* the new header content
1026
this.changeHeaderEvent = this.createEvent(EVENT_TYPES.CHANGE_HEADER);
1027
this.changeHeaderEvent.signature = SIGNATURE;
1030
* CustomEvent fired when the body content of the Module is modified
1031
* @event changeBodyEvent
1032
* @param {String/HTMLElement} content String/element representing
1033
* the new body content
1035
this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY);
1036
this.changeBodyEvent.signature = SIGNATURE;
1039
* CustomEvent fired when the footer content of the Module
1041
* @event changeFooterEvent
1042
* @param {String/HTMLElement} content String/element representing
1043
* the new footer content
1045
this.changeFooterEvent = this.createEvent(EVENT_TYPES.CHANGE_FOOTER);
1046
this.changeFooterEvent.signature = SIGNATURE;
1049
* CustomEvent fired when the content of the Module is modified
1050
* @event changeContentEvent
1052
this.changeContentEvent = this.createEvent(EVENT_TYPES.CHANGE_CONTENT);
1053
this.changeContentEvent.signature = SIGNATURE;
1056
* CustomEvent fired when the Module is destroyed
1057
* @event destroyEvent
1059
this.destroyEvent = this.createEvent(EVENT_TYPES.DESTORY);
1060
this.destroyEvent.signature = SIGNATURE;
1063
* CustomEvent fired before the Module is shown
1064
* @event beforeShowEvent
1066
this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW);
1067
this.beforeShowEvent.signature = SIGNATURE;
1070
* CustomEvent fired after the Module is shown
1073
this.showEvent = this.createEvent(EVENT_TYPES.SHOW);
1074
this.showEvent.signature = SIGNATURE;
1077
* CustomEvent fired before the Module is hidden
1078
* @event beforeHideEvent
1080
this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE);
1081
this.beforeHideEvent.signature = SIGNATURE;
1084
* CustomEvent fired after the Module is hidden
1087
this.hideEvent = this.createEvent(EVENT_TYPES.HIDE);
1088
this.hideEvent.signature = SIGNATURE;
1092
* String representing the current user-agent platform
1093
* @property platform
1096
platform: function () {
1097
var ua = navigator.userAgent.toLowerCase();
1099
if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
1101
} else if (ua.indexOf("macintosh") != -1) {
1109
* String representing the user-agent of the browser
1110
* @deprecated Use YAHOO.env.ua
1114
browser: function () {
1115
var ua = navigator.userAgent.toLowerCase();
1117
Check Opera first in case of spoof and check Safari before
1118
Gecko since Safari's user agent string includes "like Gecko"
1120
if (ua.indexOf('opera') != -1) {
1122
} else if (ua.indexOf('msie 7') != -1) {
1124
} else if (ua.indexOf('msie') != -1) {
1126
} else if (ua.indexOf('safari') != -1) {
1128
} else if (ua.indexOf('gecko') != -1) {
1136
* Boolean representing whether or not the current browsing context is
1138
* @property isSecure
1141
isSecure: function () {
1142
if (window.location.href.toLowerCase().indexOf("https") === 0) {
1150
* Initializes the custom events for Module which are fired
1151
* automatically at appropriate times by the Module class.
1153
initDefaultConfig: function () {
1154
// Add properties //
1156
* Specifies whether the Module is visible on the page.
1161
this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, {
1162
handler: this.configVisible,
1163
value: DEFAULT_CONFIG.VISIBLE.value,
1164
validator: DEFAULT_CONFIG.VISIBLE.validator
1169
* Object or array of objects representing the ContainerEffect
1170
* classes that are active for animating the container.
1173
* <strong>NOTE:</strong> Although this configuration
1174
* property is introduced at the Module level, an out of the box
1175
* implementation is not shipped for the Module class so setting
1176
* the proroperty on the Module class has no effect. The Overlay
1177
* class is the first class to provide out of the box ContainerEffect
1184
this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, {
1185
suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent,
1186
supercedes: DEFAULT_CONFIG.EFFECT.supercedes
1190
* Specifies whether to create a special proxy iframe to monitor
1191
* for user font resizing in the document
1192
* @config monitorresize
1196
this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, {
1197
handler: this.configMonitorResize,
1198
value: DEFAULT_CONFIG.MONITOR_RESIZE.value
1202
* Specifies if the module should be rendered as the first child
1203
* of document.body or appended as the last child when render is called
1204
* with document.body as the "appendToNode".
1206
* Appending to the body while the DOM is still being constructed can
1207
* lead to Operation Aborted errors in IE hence this flag is set to
1211
* @config appendtodocumentbody
1215
this.cfg.addProperty(DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.key, {
1216
value: DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.value
1221
* The Module class's initialization method, which is executed for
1222
* Module and all of its subclasses. This method is automatically
1223
* called by the constructor, and sets up all DOM references for
1224
* pre-existing markup, and creates required markup if it is not
1227
* @param {String} el The element ID representing the Module <em>OR</em>
1228
* @param {HTMLElement} el The element representing the Module
1229
* @param {Object} userConfig The configuration Object literal
1230
* containing the configuration that should be set for this module.
1231
* See configuration documentation for more details.
1233
init: function (el, userConfig) {
1238
this.beforeInitEvent.fire(Module);
1241
* The Module's Config object used for monitoring
1242
* configuration properties.
1244
* @type YAHOO.util.Config
1246
this.cfg = new Config(this);
1248
if (this.isSecure) {
1249
this.imageRoot = Module.IMG_ROOT_SSL;
1252
if (typeof el == "string") {
1254
el = document.getElementById(el);
1256
el = (createModuleTemplate()).cloneNode(false);
1267
child = this.element.firstChild;
1270
var fndHd = false, fndBd = false, fndFt = false;
1272
// We're looking for elements
1273
if (1 == child.nodeType) {
1274
if (!fndHd && Dom.hasClass(child, Module.CSS_HEADER)) {
1275
this.header = child;
1277
} else if (!fndBd && Dom.hasClass(child, Module.CSS_BODY)) {
1280
} else if (!fndFt && Dom.hasClass(child, Module.CSS_FOOTER)){
1281
this.footer = child;
1285
} while ((child = child.nextSibling));
1288
this.initDefaultConfig();
1290
Dom.addClass(this.element, Module.CSS_MODULE);
1293
this.cfg.applyConfig(userConfig, true);
1297
Subscribe to the fireQueue() method of Config so that any
1298
queued configuration changes are excecuted upon render of
1302
if (!Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) {
1303
this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
1306
this.initEvent.fire(Module);
1310
* Initialize an empty IFRAME that is placed out of the visible area
1311
* that can be used to detect text resize.
1312
* @method initResizeMonitor
1314
initResizeMonitor: function () {
1316
var isGeckoWin = (YAHOO.env.ua.gecko && this.platform == "windows");
1318
// Help prevent spinning loading icon which
1319
// started with FireFox 2.0.0.8/Win
1321
setTimeout(function(){self._initResizeMonitor();}, 0);
1323
this._initResizeMonitor();
1328
* Create and initialize the text resize monitoring iframe.
1331
* @method _initResizeMonitor
1333
_initResizeMonitor : function() {
1339
function fireTextResize() {
1340
Module.textResizeEvent.fire();
1343
if (!YAHOO.env.ua.opera) {
1344
oIFrame = Dom.get("_yuiResizeMonitor");
1346
var supportsCWResize = this._supportsCWResize();
1349
oIFrame = document.createElement("iframe");
1351
if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && YAHOO.env.ua.ie) {
1352
oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL;
1355
if (!supportsCWResize) {
1356
// Can't monitor on contentWindow, so fire from inside iframe
1357
sHTML = ["<html><head><script ",
1358
"type=\"text/javascript\">",
1359
"window.onresize=function(){window.parent.",
1360
"YAHOO.widget.Module.textResizeEvent.",
1363
"<body></body></html>"].join('');
1365
oIFrame.src = "data:text/html;charset=utf-8," + encodeURIComponent(sHTML);
1368
oIFrame.id = "_yuiResizeMonitor";
1369
oIFrame.title = "Text Resize Monitor";
1371
Need to set "position" property before inserting the
1372
iframe into the document or Safari's status bar will
1373
forever indicate the iframe is loading
1374
(See SourceForge bug #1723064)
1376
oIFrame.style.position = "absolute";
1377
oIFrame.style.visibility = "hidden";
1379
var db = document.body,
1382
db.insertBefore(oIFrame, fc);
1384
db.appendChild(oIFrame);
1387
oIFrame.style.width = "10em";
1388
oIFrame.style.height = "10em";
1389
oIFrame.style.top = (-1 * oIFrame.offsetHeight) + "px";
1390
oIFrame.style.left = (-1 * oIFrame.offsetWidth) + "px";
1391
oIFrame.style.borderWidth = "0";
1392
oIFrame.style.visibility = "visible";
1395
Don't open/close the document for Gecko like we used to, since it
1396
leads to duplicate cookies. (See SourceForge bug #1721755)
1398
if (YAHOO.env.ua.webkit) {
1399
oDoc = oIFrame.contentWindow.document;
1405
if (oIFrame && oIFrame.contentWindow) {
1406
Module.textResizeEvent.subscribe(this.onDomResize, this, true);
1408
if (!Module.textResizeInitialized) {
1409
if (supportsCWResize) {
1410
if (!Event.on(oIFrame.contentWindow, "resize", fireTextResize)) {
1412
This will fail in IE if document.domain has
1413
changed, so we must change the listener to
1414
use the oIFrame element instead
1416
Event.on(oIFrame, "resize", fireTextResize);
1419
Module.textResizeInitialized = true;
1421
this.resizeMonitor = oIFrame;
1427
* Text resize monitor helper method.
1428
* Determines if the browser supports resize events on iframe content windows.
1431
* @method _supportsCWResize
1433
_supportsCWResize : function() {
1435
Gecko 1.8.0 (FF1.5), 1.8.1.0-5 (FF2) won't fire resize on contentWindow.
1436
Gecko 1.8.1.6+ (FF2.0.0.6+) and all other browsers will fire resize on contentWindow.
1438
We don't want to start sniffing for patch versions, so fire textResize the same
1439
way on all FF, until 1.9 (3.x) is out
1441
var bSupported = true;
1442
if (YAHOO.env.ua.gecko && YAHOO.env.ua.gecko <= 1.8) {
1445
var v = navigator.userAgent.match(/rv:([^\s\)]*)/); // From YAHOO.env.ua
1447
var sv = v[0].match(/\d\.\d\.(\d)/);
1449
if (parseInt(sv[1], 10) > 0) {
1460
* Event handler fired when the resize monitor element is resized.
1461
* @method onDomResize
1462
* @param {DOMEvent} e The DOM resize event
1463
* @param {Object} obj The scope object passed to the handler
1465
onDomResize: function (e, obj) {
1467
var nLeft = -1 * this.resizeMonitor.offsetWidth,
1468
nTop = -1 * this.resizeMonitor.offsetHeight;
1470
this.resizeMonitor.style.top = nTop + "px";
1471
this.resizeMonitor.style.left = nLeft + "px";
1476
* Sets the Module's header content to the string specified, or appends
1477
* the passed element to the header. If no header is present, one will
1478
* be automatically created. An empty string can be passed to the method
1479
* to clear the contents of the header.
1482
* @param {String} headerContent The string used to set the header.
1483
* As a convenience, non HTMLElement objects can also be passed into
1484
* the method, and will be treated as strings, with the header innerHTML
1485
* set to their default toString implementations.
1487
* @param {HTMLElement} headerContent The HTMLElement to append to
1489
* @param {DocumentFragment} headerContent The document fragment
1490
* containing elements which are to be added to the header
1492
setHeader: function (headerContent) {
1493
var oHeader = this.header || (this.header = createHeader());
1495
if (headerContent.nodeName) {
1496
oHeader.innerHTML = "";
1497
oHeader.appendChild(headerContent);
1499
oHeader.innerHTML = headerContent;
1502
this.changeHeaderEvent.fire(headerContent);
1503
this.changeContentEvent.fire();
1508
* Appends the passed element to the header. If no header is present,
1509
* one will be automatically created.
1510
* @method appendToHeader
1511
* @param {HTMLElement | DocumentFragment} element The element to
1512
* append to the header. In the case of a document fragment, the
1513
* children of the fragment will be appended to the header.
1515
appendToHeader: function (element) {
1516
var oHeader = this.header || (this.header = createHeader());
1518
oHeader.appendChild(element);
1520
this.changeHeaderEvent.fire(element);
1521
this.changeContentEvent.fire();
1526
* Sets the Module's body content to the HTML specified.
1528
* If no body is present, one will be automatically created.
1530
* An empty string can be passed to the method to clear the contents of the body.
1532
* @param {String} bodyContent The HTML used to set the body.
1533
* As a convenience, non HTMLElement objects can also be passed into
1534
* the method, and will be treated as strings, with the body innerHTML
1535
* set to their default toString implementations.
1537
* @param {HTMLElement} bodyContent The HTMLElement to add as the first and only
1538
* child of the body element.
1540
* @param {DocumentFragment} bodyContent The document fragment
1541
* containing elements which are to be added to the body
1543
setBody: function (bodyContent) {
1544
var oBody = this.body || (this.body = createBody());
1546
if (bodyContent.nodeName) {
1547
oBody.innerHTML = "";
1548
oBody.appendChild(bodyContent);
1550
oBody.innerHTML = bodyContent;
1553
this.changeBodyEvent.fire(bodyContent);
1554
this.changeContentEvent.fire();
1558
* Appends the passed element to the body. If no body is present, one
1559
* will be automatically created.
1560
* @method appendToBody
1561
* @param {HTMLElement | DocumentFragment} element The element to
1562
* append to the body. In the case of a document fragment, the
1563
* children of the fragment will be appended to the body.
1566
appendToBody: function (element) {
1567
var oBody = this.body || (this.body = createBody());
1569
oBody.appendChild(element);
1571
this.changeBodyEvent.fire(element);
1572
this.changeContentEvent.fire();
1577
* Sets the Module's footer content to the HTML specified, or appends
1578
* the passed element to the footer. If no footer is present, one will
1579
* be automatically created. An empty string can be passed to the method
1580
* to clear the contents of the footer.
1582
* @param {String} footerContent The HTML used to set the footer
1583
* As a convenience, non HTMLElement objects can also be passed into
1584
* the method, and will be treated as strings, with the footer innerHTML
1585
* set to their default toString implementations.
1587
* @param {HTMLElement} footerContent The HTMLElement to append to
1590
* @param {DocumentFragment} footerContent The document fragment containing
1591
* elements which are to be added to the footer
1593
setFooter: function (footerContent) {
1595
var oFooter = this.footer || (this.footer = createFooter());
1597
if (footerContent.nodeName) {
1598
oFooter.innerHTML = "";
1599
oFooter.appendChild(footerContent);
1601
oFooter.innerHTML = footerContent;
1604
this.changeFooterEvent.fire(footerContent);
1605
this.changeContentEvent.fire();
1609
* Appends the passed element to the footer. If no footer is present,
1610
* one will be automatically created.
1611
* @method appendToFooter
1612
* @param {HTMLElement | DocumentFragment} element The element to
1613
* append to the footer. In the case of a document fragment, the
1614
* children of the fragment will be appended to the footer
1616
appendToFooter: function (element) {
1618
var oFooter = this.footer || (this.footer = createFooter());
1620
oFooter.appendChild(element);
1622
this.changeFooterEvent.fire(element);
1623
this.changeContentEvent.fire();
1628
* Renders the Module by inserting the elements that are not already
1629
* in the main Module into their correct places. Optionally appends
1630
* the Module to the specified node prior to the render's execution.
1632
* For Modules without existing markup, the appendToNode argument
1633
* is REQUIRED. If this argument is ommitted and the current element is
1634
* not present in the document, the function will return false,
1635
* indicating that the render was a failure.
1638
* NOTE: As of 2.3.1, if the appendToNode is the document's body element
1639
* then the module is rendered as the first child of the body element,
1640
* and not appended to it, to avoid Operation Aborted errors in IE when
1641
* rendering the module before window's load event is fired. You can
1642
* use the appendtodocumentbody configuration property to change this
1643
* to append to document.body if required.
1646
* @param {String} appendToNode The element id to which the Module
1647
* should be appended to prior to rendering <em>OR</em>
1648
* @param {HTMLElement} appendToNode The element to which the Module
1649
* should be appended to prior to rendering
1650
* @param {HTMLElement} moduleElement OPTIONAL. The element that
1651
* represents the actual Standard Module container.
1652
* @return {Boolean} Success or failure of the render
1654
render: function (appendToNode, moduleElement) {
1659
function appendTo(parentNode) {
1660
if (typeof parentNode == "string") {
1661
parentNode = document.getElementById(parentNode);
1665
me._addToParent(parentNode, me.element);
1666
me.appendEvent.fire();
1670
this.beforeRenderEvent.fire();
1672
if (! moduleElement) {
1673
moduleElement = this.element;
1677
appendTo(appendToNode);
1679
// No node was passed in. If the element is not already in the Dom, this fails
1680
if (! Dom.inDocument(this.element)) {
1681
YAHOO.log("Render failed. Must specify appendTo node if " + " Module isn't already in the DOM.", "error");
1686
// Need to get everything into the DOM if it isn't already
1687
if (this.header && ! Dom.inDocument(this.header)) {
1688
// There is a header, but it's not in the DOM yet. Need to add it.
1689
firstChild = moduleElement.firstChild;
1691
moduleElement.insertBefore(this.header, firstChild);
1693
moduleElement.appendChild(this.header);
1697
if (this.body && ! Dom.inDocument(this.body)) {
1698
// There is a body, but it's not in the DOM yet. Need to add it.
1699
if (this.footer && Dom.isAncestor(this.moduleElement, this.footer)) {
1700
moduleElement.insertBefore(this.body, this.footer);
1702
moduleElement.appendChild(this.body);
1706
if (this.footer && ! Dom.inDocument(this.footer)) {
1707
// There is a footer, but it's not in the DOM yet. Need to add it.
1708
moduleElement.appendChild(this.footer);
1711
this.renderEvent.fire();
1716
* Removes the Module element from the DOM and sets all child elements
1720
destroy: function () {
1726
Event.purgeElement(this.element, true);
1727
parent = this.element.parentNode;
1731
parent.removeChild(this.element);
1734
this.element = null;
1739
Module.textResizeEvent.unsubscribe(this.onDomResize, this);
1744
this.destroyEvent.fire();
1748
* Shows the Module element by setting the visible configuration
1749
* property to true. Also fires two events: beforeShowEvent prior to
1750
* the visibility change, and showEvent after.
1754
this.cfg.setProperty("visible", true);
1758
* Hides the Module element by setting the visible configuration
1759
* property to false. Also fires two events: beforeHideEvent prior to
1760
* the visibility change, and hideEvent after.
1764
this.cfg.setProperty("visible", false);
1767
// BUILT-IN EVENT HANDLERS FOR MODULE //
1769
* Default event handler for changing the visibility property of a
1770
* Module. By default, this is achieved by switching the "display" style
1771
* between "block" and "none".
1772
* This method is responsible for firing showEvent and hideEvent.
1773
* @param {String} type The CustomEvent type (usually the property name)
1774
* @param {Object[]} args The CustomEvent arguments. For configuration
1775
* handlers, args[0] will equal the newly applied value for the property.
1776
* @param {Object} obj The scope object. For configuration handlers,
1777
* this will usually equal the owner.
1778
* @method configVisible
1780
configVisible: function (type, args, obj) {
1781
var visible = args[0];
1783
this.beforeShowEvent.fire();
1784
Dom.setStyle(this.element, "display", "block");
1785
this.showEvent.fire();
1787
this.beforeHideEvent.fire();
1788
Dom.setStyle(this.element, "display", "none");
1789
this.hideEvent.fire();
1794
* Default event handler for the "monitorresize" configuration property
1795
* @param {String} type The CustomEvent type (usually the property name)
1796
* @param {Object[]} args The CustomEvent arguments. For configuration
1797
* handlers, args[0] will equal the newly applied value for the property.
1798
* @param {Object} obj The scope object. For configuration handlers,
1799
* this will usually equal the owner.
1800
* @method configMonitorResize
1802
configMonitorResize: function (type, args, obj) {
1803
var monitor = args[0];
1805
this.initResizeMonitor();
1807
Module.textResizeEvent.unsubscribe(this.onDomResize, this, true);
1808
this.resizeMonitor = null;
1813
* This method is a protected helper, used when constructing the DOM structure for the module
1814
* to account for situations which may cause Operation Aborted errors in IE. It should not
1815
* be used for general DOM construction.
1817
* If the parentNode is not document.body, the element is appended as the last element.
1820
* If the parentNode is document.body the element is added as the first child to help
1821
* prevent Operation Aborted errors in IE.
1824
* @param {parentNode} The HTML element to which the element will be added
1825
* @param {element} The HTML element to be added to parentNode's children
1826
* @method _addToParent
1829
_addToParent: function(parentNode, element) {
1830
if (!this.cfg.getProperty("appendtodocumentbody") && parentNode === document.body && parentNode.firstChild) {
1831
parentNode.insertBefore(element, parentNode.firstChild);
1833
parentNode.appendChild(element);
1838
* Returns a String representation of the Object.
1840
* @return {String} The string representation of the Module
1842
toString: function () {
1843
return "Module " + this.id;
1847
YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
1854
* Overlay is a Module that is absolutely positioned above the page flow. It
1855
* has convenience methods for positioning and sizing, as well as options for
1856
* controlling zIndex and constraining the Overlay's position to the current
1857
* visible viewport. Overlay also contains a dynamicly generated IFRAME which
1858
* is placed beneath it for Internet Explorer 6 and 5.x so that it will be
1859
* properly rendered above SELECT elements.
1860
* @namespace YAHOO.widget
1862
* @extends YAHOO.widget.Module
1863
* @param {String} el The element ID representing the Overlay <em>OR</em>
1864
* @param {HTMLElement} el The element representing the Overlay
1865
* @param {Object} userConfig The configuration object literal containing
1866
* the configuration that should be set for this Overlay. See configuration
1867
* documentation for more details.
1870
YAHOO.widget.Overlay = function (el, userConfig) {
1871
YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
1874
var Lang = YAHOO.lang,
1875
CustomEvent = YAHOO.util.CustomEvent,
1876
Module = YAHOO.widget.Module,
1877
Event = YAHOO.util.Event,
1878
Dom = YAHOO.util.Dom,
1879
Config = YAHOO.util.Config,
1881
Overlay = YAHOO.widget.Overlay,
1883
_SUBSCRIBE = "subscribe",
1884
_UNSUBSCRIBE = "unsubscribe",
1889
* Constant representing the name of the Overlay's events
1890
* @property EVENT_TYPES
1896
"BEFORE_MOVE": "beforeMove",
1901
* Constant representing the Overlay's configuration properties
1902
* @property DEFAULT_CONFIG
1911
validator: Lang.isNumber,
1912
suppressEvent: true,
1913
supercedes: ["iframe"]
1918
validator: Lang.isNumber,
1919
suppressEvent: true,
1920
supercedes: ["iframe"]
1925
suppressEvent: true,
1926
supercedes: ["iframe"]
1931
suppressEvent: true,
1932
supercedes: ["iframe"]
1938
validator: Lang.isBoolean,
1939
supercedes: ["iframe", "visible"]
1944
suppressEvent: true,
1945
supercedes: ["context", "fixedcenter", "iframe"]
1950
suppressEvent: true,
1951
supercedes: ["context", "fixedcenter", "iframe"]
1954
"AUTO_FILL_HEIGHT" : {
1955
key: "autofillheight",
1957
supercedes: ["height"],
1966
"CONSTRAIN_TO_VIEWPORT": {
1967
key: "constraintoviewport",
1969
validator: Lang.isBoolean,
1970
supercedes: ["iframe", "x", "y", "xy"]
1975
value: (UA.ie == 6 ? true : false),
1976
validator: Lang.isBoolean,
1977
supercedes: ["zindex"]
1980
"PREVENT_CONTEXT_OVERLAP": {
1981
key: "preventcontextoverlap",
1983
validator: Lang.isBoolean,
1984
supercedes: ["constraintoviewport"]
1990
* The URL that will be placed in the iframe
1991
* @property YAHOO.widget.Overlay.IFRAME_SRC
1996
Overlay.IFRAME_SRC = "javascript:false;";
1999
* Number representing how much the iframe shim should be offset from each
2000
* side of an Overlay instance, in pixels.
2001
* @property YAHOO.widget.Overlay.IFRAME_SRC
2007
Overlay.IFRAME_OFFSET = 3;
2010
* Number representing the minimum distance an Overlay instance should be
2011
* positioned relative to the boundaries of the browser's viewport, in pixels.
2012
* @property YAHOO.widget.Overlay.VIEWPORT_OFFSET
2018
Overlay.VIEWPORT_OFFSET = 10;
2021
* Constant representing the top left corner of an element, used for
2022
* configuring the context element alignment
2023
* @property YAHOO.widget.Overlay.TOP_LEFT
2028
Overlay.TOP_LEFT = "tl";
2031
* Constant representing the top right corner of an element, used for
2032
* configuring the context element alignment
2033
* @property YAHOO.widget.Overlay.TOP_RIGHT
2038
Overlay.TOP_RIGHT = "tr";
2041
* Constant representing the top bottom left corner of an element, used for
2042
* configuring the context element alignment
2043
* @property YAHOO.widget.Overlay.BOTTOM_LEFT
2048
Overlay.BOTTOM_LEFT = "bl";
2051
* Constant representing the bottom right corner of an element, used for
2052
* configuring the context element alignment
2053
* @property YAHOO.widget.Overlay.BOTTOM_RIGHT
2058
Overlay.BOTTOM_RIGHT = "br";
2061
* Constant representing the default CSS class used for an Overlay
2062
* @property YAHOO.widget.Overlay.CSS_OVERLAY
2067
Overlay.CSS_OVERLAY = "yui-overlay";
2070
* Constant representing the names of the standard module elements
2071
* used in the overlay.
2072
* @property YAHOO.widget.Overlay.STD_MOD_RE
2077
Overlay.STD_MOD_RE = /^\s*?(body|footer|header)\s*?$/i;
2080
* A singleton CustomEvent used for reacting to the DOM event for
2082
* @event YAHOO.widget.Overlay.windowScrollEvent
2084
Overlay.windowScrollEvent = new CustomEvent("windowScroll");
2087
* A singleton CustomEvent used for reacting to the DOM event for
2089
* @event YAHOO.widget.Overlay.windowResizeEvent
2091
Overlay.windowResizeEvent = new CustomEvent("windowResize");
2094
* The DOM event handler used to fire the CustomEvent for window scroll
2095
* @method YAHOO.widget.Overlay.windowScrollHandler
2097
* @param {DOMEvent} e The DOM scroll event
2099
Overlay.windowScrollHandler = function (e) {
2100
var t = Event.getTarget(e);
2102
// - Webkit (Safari 2/3) and Opera 9.2x bubble scroll events from elements to window
2103
// - FF2/3 and IE6/7, Opera 9.5x don't bubble scroll events from elements to window
2104
// - IE doesn't recognize scroll registered on the document.
2106
// Also, when document view is scrolled, IE doesn't provide a target,
2107
// rest of the browsers set target to window.document, apart from opera
2108
// which sets target to window.
2109
if (!t || t === window || t === window.document) {
2112
if (! window.scrollEnd) {
2113
window.scrollEnd = -1;
2116
clearTimeout(window.scrollEnd);
2118
window.scrollEnd = setTimeout(function () {
2119
Overlay.windowScrollEvent.fire();
2123
Overlay.windowScrollEvent.fire();
2129
* The DOM event handler used to fire the CustomEvent for window resize
2130
* @method YAHOO.widget.Overlay.windowResizeHandler
2132
* @param {DOMEvent} e The DOM resize event
2134
Overlay.windowResizeHandler = function (e) {
2137
if (! window.resizeEnd) {
2138
window.resizeEnd = -1;
2141
clearTimeout(window.resizeEnd);
2143
window.resizeEnd = setTimeout(function () {
2144
Overlay.windowResizeEvent.fire();
2147
Overlay.windowResizeEvent.fire();
2152
* A boolean that indicated whether the window resize and scroll events have
2153
* already been subscribed to.
2154
* @property YAHOO.widget.Overlay._initialized
2158
Overlay._initialized = null;
2160
if (Overlay._initialized === null) {
2161
Event.on(window, "scroll", Overlay.windowScrollHandler);
2162
Event.on(window, "resize", Overlay.windowResizeHandler);
2163
Overlay._initialized = true;
2167
* Internal map of special event types, which are provided
2168
* by the instance. It maps the event type to the custom event
2169
* instance. Contains entries for the "windowScroll", "windowResize" and
2170
* "textResize" static container events.
2172
* @property YAHOO.widget.Overlay._TRIGGER_MAP
2177
Overlay._TRIGGER_MAP = {
2178
"windowScroll" : Overlay.windowScrollEvent,
2179
"windowResize" : Overlay.windowResizeEvent,
2180
"textResize" : Module.textResizeEvent
2183
YAHOO.extend(Overlay, Module, {
2187
* Array of default event types which will trigger
2188
* context alignment for the Overlay class.
2190
* <p>The array is empty by default for Overlay,
2191
* but maybe populated in future releases, so classes extending
2192
* Overlay which need to define their own set of CONTEXT_TRIGGERS
2193
* should concatenate their super class's prototype.CONTEXT_TRIGGERS
2194
* value with their own array of values.
2198
* <code>CustomOverlay.prototype.CONTEXT_TRIGGERS = YAHOO.widget.Overlay.prototype.CONTEXT_TRIGGERS.concat(["windowScroll"]);</code>
2201
* @property CONTEXT_TRIGGERS
2205
CONTEXT_TRIGGERS : [],
2208
* The Overlay initialization method, which is executed for Overlay and
2209
* all of its subclasses. This method is automatically called by the
2210
* constructor, and sets up all DOM references for pre-existing markup,
2211
* and creates required markup if it is not already present.
2213
* @param {String} el The element ID representing the Overlay <em>OR</em>
2214
* @param {HTMLElement} el The element representing the Overlay
2215
* @param {Object} userConfig The configuration object literal
2216
* containing the configuration that should be set for this Overlay.
2217
* See configuration documentation for more details.
2219
init: function (el, userConfig) {
2222
Note that we don't pass the user config in here yet because we
2223
only want it executed once, at the lowest subclass level
2226
Overlay.superclass.init.call(this, el/*, userConfig*/);
2228
this.beforeInitEvent.fire(Overlay);
2230
Dom.addClass(this.element, Overlay.CSS_OVERLAY);
2233
this.cfg.applyConfig(userConfig, true);
2236
if (this.platform == "mac" && UA.gecko) {
2238
if (! Config.alreadySubscribed(this.showEvent,
2239
this.showMacGeckoScrollbars, this)) {
2241
this.showEvent.subscribe(this.showMacGeckoScrollbars,
2246
if (! Config.alreadySubscribed(this.hideEvent,
2247
this.hideMacGeckoScrollbars, this)) {
2249
this.hideEvent.subscribe(this.hideMacGeckoScrollbars,
2255
this.initEvent.fire(Overlay);
2259
* Initializes the custom events for Overlay which are fired
2260
* automatically at appropriate times by the Overlay class.
2261
* @method initEvents
2263
initEvents: function () {
2265
Overlay.superclass.initEvents.call(this);
2267
var SIGNATURE = CustomEvent.LIST;
2270
* CustomEvent fired before the Overlay is moved.
2271
* @event beforeMoveEvent
2272
* @param {Number} x x coordinate
2273
* @param {Number} y y coordinate
2275
this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
2276
this.beforeMoveEvent.signature = SIGNATURE;
2279
* CustomEvent fired after the Overlay is moved.
2281
* @param {Number} x x coordinate
2282
* @param {Number} y y coordinate
2284
this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
2285
this.moveEvent.signature = SIGNATURE;
2290
* Initializes the class's configurable properties which can be changed
2291
* using the Overlay's Config object (cfg).
2292
* @method initDefaultConfig
2294
initDefaultConfig: function () {
2296
Overlay.superclass.initDefaultConfig.call(this);
2300
// Add overlay config properties //
2303
* The absolute x-coordinate position of the Overlay
2308
cfg.addProperty(DEFAULT_CONFIG.X.key, {
2310
handler: this.configX,
2311
validator: DEFAULT_CONFIG.X.validator,
2312
suppressEvent: DEFAULT_CONFIG.X.suppressEvent,
2313
supercedes: DEFAULT_CONFIG.X.supercedes
2318
* The absolute y-coordinate position of the Overlay
2323
cfg.addProperty(DEFAULT_CONFIG.Y.key, {
2325
handler: this.configY,
2326
validator: DEFAULT_CONFIG.Y.validator,
2327
suppressEvent: DEFAULT_CONFIG.Y.suppressEvent,
2328
supercedes: DEFAULT_CONFIG.Y.supercedes
2333
* An array with the absolute x and y positions of the Overlay
2338
cfg.addProperty(DEFAULT_CONFIG.XY.key, {
2339
handler: this.configXY,
2340
suppressEvent: DEFAULT_CONFIG.XY.suppressEvent,
2341
supercedes: DEFAULT_CONFIG.XY.supercedes
2346
* The array of context arguments for context-sensitive positioning.
2350
* The format of the array is: <code>[contextElementOrId, overlayCorner, contextCorner, arrayOfTriggerEvents (optional)]</code>, the
2351
* the 4 array elements described in detail below:
2355
* <dt>contextElementOrId <String|HTMLElement></dt>
2356
* <dd>A reference to the context element to which the overlay should be aligned (or it's id).</dd>
2357
* <dt>overlayCorner <String></dt>
2358
* <dd>The corner of the overlay which is to be used for alignment. This corner will be aligned to the
2359
* corner of the context element defined by the "contextCorner" entry which follows. Supported string values are:
2360
* "tr" (top right), "tl" (top left), "br" (bottom right), or "bl" (bottom left).</dd>
2361
* <dt>contextCorner <String></dt>
2362
* <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>
2363
* <dt>arrayOfTriggerEvents (optional) <Array[String|CustomEvent]></dt>
2366
* 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>
2367
* 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.
2368
* This is useful in situations where the layout of the document may change, resulting in the context element's position being modified.
2371
* The array can contain either event type strings for events the instance publishes (e.g. "beforeShow") or CustomEvent instances. Additionally the following
2372
* 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).
2378
* For example, setting this property to <code>["img1", "tl", "bl"]</code> will
2379
* align the Overlay's top left corner to the bottom left corner of the
2380
* context element with id "img1".
2383
* Adding the optional trigger values: <code>["img1", "tl", "bl", ["beforeShow", "windowResize"]]</code>,
2384
* will re-align the overlay position, whenever the "beforeShow" or "windowResize" events are fired.
2391
cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
2392
handler: this.configContext,
2393
suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent,
2394
supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
2398
* True if the Overlay should be anchored to the center of
2400
* @config fixedcenter
2404
cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
2405
handler: this.configFixedCenter,
2406
value: DEFAULT_CONFIG.FIXED_CENTER.value,
2407
validator: DEFAULT_CONFIG.FIXED_CENTER.validator,
2408
supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
2412
* CSS width of the Overlay.
2417
cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
2418
handler: this.configWidth,
2419
suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent,
2420
supercedes: DEFAULT_CONFIG.WIDTH.supercedes
2424
* CSS height of the Overlay.
2429
cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
2430
handler: this.configHeight,
2431
suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent,
2432
supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
2436
* Standard module element which should auto fill out the height of the Overlay if the height config property is set.
2437
* Supported values are "header", "body", "footer".
2439
* @config autofillheight
2443
cfg.addProperty(DEFAULT_CONFIG.AUTO_FILL_HEIGHT.key, {
2444
handler: this.configAutoFillHeight,
2445
value : DEFAULT_CONFIG.AUTO_FILL_HEIGHT.value,
2446
validator : this._validateAutoFill,
2447
suppressEvent: DEFAULT_CONFIG.AUTO_FILL_HEIGHT.suppressEvent,
2448
supercedes: DEFAULT_CONFIG.AUTO_FILL_HEIGHT.supercedes
2452
* CSS z-index of the Overlay.
2457
cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
2458
handler: this.configzIndex,
2459
value: DEFAULT_CONFIG.ZINDEX.value
2463
* True if the Overlay should be prevented from being positioned
2464
* out of the viewport.
2465
* @config constraintoviewport
2469
cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
2471
handler: this.configConstrainToViewport,
2472
value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value,
2473
validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator,
2474
supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
2480
* @description Boolean indicating whether or not the Overlay should
2481
* have an IFRAME shim; used to prevent SELECT elements from
2482
* poking through an Overlay instance in IE6. When set to "true",
2483
* the iframe shim is created when the Overlay instance is intially
2486
* @default true for IE6 and below, false for all other browsers.
2488
cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
2490
handler: this.configIframe,
2491
value: DEFAULT_CONFIG.IFRAME.value,
2492
validator: DEFAULT_CONFIG.IFRAME.validator,
2493
supercedes: DEFAULT_CONFIG.IFRAME.supercedes
2498
* @config preventcontextoverlap
2499
* @description Boolean indicating whether or not the Overlay should overlap its
2500
* context element (defined using the "context" configuration property) when the
2501
* "constraintoviewport" configuration property is set to "true".
2505
cfg.addProperty(DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.key, {
2507
value: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.value,
2508
validator: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.validator,
2509
supercedes: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.supercedes
2516
* Moves the Overlay to the specified position. This function is
2517
* identical to calling this.cfg.setProperty("xy", [x,y]);
2519
* @param {Number} x The Overlay's new x position
2520
* @param {Number} y The Overlay's new y position
2522
moveTo: function (x, y) {
2523
this.cfg.setProperty("xy", [x, y]);
2527
* Adds a CSS class ("hide-scrollbars") and removes a CSS class
2528
* ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X
2529
* (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2530
* @method hideMacGeckoScrollbars
2532
hideMacGeckoScrollbars: function () {
2533
Dom.replaceClass(this.element, "show-scrollbars", "hide-scrollbars");
2537
* Adds a CSS class ("show-scrollbars") and removes a CSS class
2538
* ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X
2539
* (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2540
* @method showMacGeckoScrollbars
2542
showMacGeckoScrollbars: function () {
2543
Dom.replaceClass(this.element, "hide-scrollbars", "show-scrollbars");
2546
// BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
2548
* The default event handler fired when the "visible" property is
2549
* changed. This method is responsible for firing showEvent
2551
* @method configVisible
2552
* @param {String} type The CustomEvent type (usually the property name)
2553
* @param {Object[]} args The CustomEvent arguments. For configuration
2554
* handlers, args[0] will equal the newly applied value for the property.
2555
* @param {Object} obj The scope object. For configuration handlers,
2556
* this will usually equal the owner.
2558
configVisible: function (type, args, obj) {
2560
var visible = args[0],
2561
currentVis = Dom.getStyle(this.element, "visibility"),
2562
effect = this.cfg.getProperty("effect"),
2563
effectInstances = [],
2564
isMacGecko = (this.platform == "mac" && UA.gecko),
2565
alreadySubscribed = Config.alreadySubscribed,
2566
eff, ei, e, i, j, k, h,
2570
if (currentVis == "inherit") {
2571
e = this.element.parentNode;
2573
while (e.nodeType != 9 && e.nodeType != 11) {
2574
currentVis = Dom.getStyle(e, "visibility");
2576
if (currentVis != "inherit") {
2583
if (currentVis == "inherit") {
2584
currentVis = "visible";
2589
if (effect instanceof Array) {
2590
nEffects = effect.length;
2592
for (i = 0; i < nEffects; i++) {
2594
effectInstances[effectInstances.length] =
2595
eff.effect(this, eff.duration);
2599
effectInstances[effectInstances.length] =
2600
effect.effect(this, effect.duration);
2605
if (visible) { // Show
2607
this.showMacGeckoScrollbars();
2610
if (effect) { // Animate in
2611
if (visible) { // Animate in if not showing
2612
if (currentVis != "visible" || currentVis === "") {
2613
this.beforeShowEvent.fire();
2614
nEffectInstances = effectInstances.length;
2616
for (j = 0; j < nEffectInstances; j++) {
2617
ei = effectInstances[j];
2618
if (j === 0 && !alreadySubscribed(
2619
ei.animateInCompleteEvent,
2620
this.showEvent.fire, this.showEvent)) {
2623
Delegate showEvent until end
2624
of animateInComplete
2627
ei.animateInCompleteEvent.subscribe(
2628
this.showEvent.fire, this.showEvent, true);
2635
if (currentVis != "visible" || currentVis === "") {
2636
this.beforeShowEvent.fire();
2638
Dom.setStyle(this.element, "visibility", "visible");
2640
this.cfg.refireEvent("iframe");
2641
this.showEvent.fire();
2647
this.hideMacGeckoScrollbars();
2650
if (effect) { // Animate out if showing
2651
if (currentVis == "visible") {
2652
this.beforeHideEvent.fire();
2654
nEffectInstances = effectInstances.length;
2655
for (k = 0; k < nEffectInstances; k++) {
2656
h = effectInstances[k];
2658
if (k === 0 && !alreadySubscribed(
2659
h.animateOutCompleteEvent, this.hideEvent.fire,
2663
Delegate hideEvent until end
2664
of animateOutComplete
2667
h.animateOutCompleteEvent.subscribe(
2668
this.hideEvent.fire, this.hideEvent, true);
2674
} else if (currentVis === "") {
2675
Dom.setStyle(this.element, "visibility", "hidden");
2678
} else { // Simple hide
2680
if (currentVis == "visible" || currentVis === "") {
2681
this.beforeHideEvent.fire();
2682
Dom.setStyle(this.element, "visibility", "hidden");
2683
this.hideEvent.fire();
2690
* Center event handler used for centering on scroll/resize, but only if
2691
* the Overlay is visible
2692
* @method doCenterOnDOMEvent
2694
doCenterOnDOMEvent: function () {
2695
if (this.cfg.getProperty("visible")) {
2701
* The default event handler fired when the "fixedcenter" property
2703
* @method configFixedCenter
2704
* @param {String} type The CustomEvent type (usually the property name)
2705
* @param {Object[]} args The CustomEvent arguments. For configuration
2706
* handlers, args[0] will equal the newly applied value for the property.
2707
* @param {Object} obj The scope object. For configuration handlers,
2708
* this will usually equal the owner.
2710
configFixedCenter: function (type, args, obj) {
2713
alreadySubscribed = Config.alreadySubscribed,
2714
windowResizeEvent = Overlay.windowResizeEvent,
2715
windowScrollEvent = Overlay.windowScrollEvent;
2720
if (!alreadySubscribed(this.beforeShowEvent, this.center, this)) {
2721
this.beforeShowEvent.subscribe(this.center);
2724
if (!alreadySubscribed(windowResizeEvent, this.doCenterOnDOMEvent, this)) {
2725
windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2728
if (!alreadySubscribed(windowScrollEvent, this.doCenterOnDOMEvent, this)) {
2729
windowScrollEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2733
this.beforeShowEvent.unsubscribe(this.center);
2735
windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2736
windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2741
* The default event handler fired when the "height" property is changed.
2742
* @method configHeight
2743
* @param {String} type The CustomEvent type (usually the property name)
2744
* @param {Object[]} args The CustomEvent arguments. For configuration
2745
* handlers, args[0] will equal the newly applied value for the property.
2746
* @param {Object} obj The scope object. For configuration handlers,
2747
* this will usually equal the owner.
2749
configHeight: function (type, args, obj) {
2751
var height = args[0],
2754
Dom.setStyle(el, "height", height);
2755
this.cfg.refireEvent("iframe");
2759
* The default event handler fired when the "autofillheight" property is changed.
2760
* @method configAutoFillHeight
2762
* @param {String} type The CustomEvent type (usually the property name)
2763
* @param {Object[]} args The CustomEvent arguments. For configuration
2764
* handlers, args[0] will equal the newly applied value for the property.
2765
* @param {Object} obj The scope object. For configuration handlers,
2766
* this will usually equal the owner.
2768
configAutoFillHeight: function (type, args, obj) {
2769
var fillEl = args[0],
2770
currEl = this.cfg.getProperty("autofillheight");
2772
this.cfg.unsubscribeFromConfigEvent("height", this._autoFillOnHeightChange);
2773
Module.textResizeEvent.unsubscribe("height", this._autoFillOnHeightChange);
2775
if (currEl && fillEl !== currEl && this[currEl]) {
2776
Dom.setStyle(this[currEl], "height", "");
2780
fillEl = Lang.trim(fillEl.toLowerCase());
2782
this.cfg.subscribeToConfigEvent("height", this._autoFillOnHeightChange, this[fillEl], this);
2783
Module.textResizeEvent.subscribe(this._autoFillOnHeightChange, this[fillEl], this);
2785
this.cfg.setProperty("autofillheight", fillEl, true);
2790
* The default event handler fired when the "width" property is changed.
2791
* @method configWidth
2792
* @param {String} type The CustomEvent type (usually the property name)
2793
* @param {Object[]} args The CustomEvent arguments. For configuration
2794
* handlers, args[0] will equal the newly applied value for the property.
2795
* @param {Object} obj The scope object. For configuration handlers,
2796
* this will usually equal the owner.
2798
configWidth: function (type, args, obj) {
2800
var width = args[0],
2803
Dom.setStyle(el, "width", width);
2804
this.cfg.refireEvent("iframe");
2808
* The default event handler fired when the "zIndex" property is changed.
2809
* @method configzIndex
2810
* @param {String} type The CustomEvent type (usually the property name)
2811
* @param {Object[]} args The CustomEvent arguments. For configuration
2812
* handlers, args[0] will equal the newly applied value for the property.
2813
* @param {Object} obj The scope object. For configuration handlers,
2814
* this will usually equal the owner.
2816
configzIndex: function (type, args, obj) {
2818
var zIndex = args[0],
2822
zIndex = Dom.getStyle(el, "zIndex");
2823
if (! zIndex || isNaN(zIndex)) {
2828
if (this.iframe || this.cfg.getProperty("iframe") === true) {
2834
Dom.setStyle(el, "zIndex", zIndex);
2835
this.cfg.setProperty("zIndex", zIndex, true);
2843
* The default event handler fired when the "xy" property is changed.
2845
* @param {String} type The CustomEvent type (usually the property name)
2846
* @param {Object[]} args The CustomEvent arguments. For configuration
2847
* handlers, args[0] will equal the newly applied value for the property.
2848
* @param {Object} obj The scope object. For configuration handlers,
2849
* this will usually equal the owner.
2851
configXY: function (type, args, obj) {
2857
this.cfg.setProperty("x", x);
2858
this.cfg.setProperty("y", y);
2860
this.beforeMoveEvent.fire([x, y]);
2862
x = this.cfg.getProperty("x");
2863
y = this.cfg.getProperty("y");
2865
YAHOO.log(("xy: " + [x, y]), "iframe");
2867
this.cfg.refireEvent("iframe");
2868
this.moveEvent.fire([x, y]);
2872
* The default event handler fired when the "x" property is changed.
2874
* @param {String} type The CustomEvent type (usually the property name)
2875
* @param {Object[]} args The CustomEvent arguments. For configuration
2876
* handlers, args[0] will equal the newly applied value for the property.
2877
* @param {Object} obj The scope object. For configuration handlers,
2878
* this will usually equal the owner.
2880
configX: function (type, args, obj) {
2883
y = this.cfg.getProperty("y");
2885
this.cfg.setProperty("x", x, true);
2886
this.cfg.setProperty("y", y, true);
2888
this.beforeMoveEvent.fire([x, y]);
2890
x = this.cfg.getProperty("x");
2891
y = this.cfg.getProperty("y");
2893
Dom.setX(this.element, x, true);
2895
this.cfg.setProperty("xy", [x, y], true);
2897
this.cfg.refireEvent("iframe");
2898
this.moveEvent.fire([x, y]);
2902
* The default event handler fired when the "y" property is changed.
2904
* @param {String} type The CustomEvent type (usually the property name)
2905
* @param {Object[]} args The CustomEvent arguments. For configuration
2906
* handlers, args[0] will equal the newly applied value for the property.
2907
* @param {Object} obj The scope object. For configuration handlers,
2908
* this will usually equal the owner.
2910
configY: function (type, args, obj) {
2912
var x = this.cfg.getProperty("x"),
2915
this.cfg.setProperty("x", x, true);
2916
this.cfg.setProperty("y", y, true);
2918
this.beforeMoveEvent.fire([x, y]);
2920
x = this.cfg.getProperty("x");
2921
y = this.cfg.getProperty("y");
2923
Dom.setY(this.element, y, true);
2925
this.cfg.setProperty("xy", [x, y], true);
2927
this.cfg.refireEvent("iframe");
2928
this.moveEvent.fire([x, y]);
2932
* Shows the iframe shim, if it has been enabled.
2933
* @method showIframe
2935
showIframe: function () {
2937
var oIFrame = this.iframe,
2941
oParentNode = this.element.parentNode;
2943
if (oParentNode != oIFrame.parentNode) {
2944
this._addToParent(oParentNode, oIFrame);
2946
oIFrame.style.display = "block";
2951
* Hides the iframe shim, if it has been enabled.
2952
* @method hideIframe
2954
hideIframe: function () {
2956
this.iframe.style.display = "none";
2961
* Syncronizes the size and position of iframe shim to that of its
2962
* corresponding Overlay instance.
2963
* @method syncIframe
2965
syncIframe: function () {
2967
var oIFrame = this.iframe,
2968
oElement = this.element,
2969
nOffset = Overlay.IFRAME_OFFSET,
2970
nDimensionOffset = (nOffset * 2),
2975
oIFrame.style.width = (oElement.offsetWidth + nDimensionOffset + "px");
2976
oIFrame.style.height = (oElement.offsetHeight + nDimensionOffset + "px");
2978
// Position <iframe>
2979
aXY = this.cfg.getProperty("xy");
2981
if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
2982
this.syncPosition();
2983
aXY = this.cfg.getProperty("xy");
2985
Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
2990
* Sets the zindex of the iframe shim, if it exists, based on the zindex of
2991
* the Overlay element. The zindex of the iframe is set to be one less
2992
* than the Overlay element's zindex.
2994
* <p>NOTE: This method will not bump up the zindex of the Overlay element
2995
* to ensure that the iframe shim has a non-negative zindex.
2996
* If you require the iframe zindex to be 0 or higher, the zindex of
2997
* the Overlay element should be set to a value greater than 0, before
2998
* this method is called.
3000
* @method stackIframe
3002
stackIframe: function () {
3004
var overlayZ = Dom.getStyle(this.element, "zIndex");
3005
if (!YAHOO.lang.isUndefined(overlayZ) && !isNaN(overlayZ)) {
3006
Dom.setStyle(this.iframe, "zIndex", (overlayZ - 1));
3012
* The default event handler fired when the "iframe" property is changed.
3013
* @method configIframe
3014
* @param {String} type The CustomEvent type (usually the property name)
3015
* @param {Object[]} args The CustomEvent arguments. For configuration
3016
* handlers, args[0] will equal the newly applied value for the property.
3017
* @param {Object} obj The scope object. For configuration handlers,
3018
* this will usually equal the owner.
3020
configIframe: function (type, args, obj) {
3022
var bIFrame = args[0];
3024
function createIFrame() {
3026
var oIFrame = this.iframe,
3027
oElement = this.element,
3031
if (!m_oIFrameTemplate) {
3032
m_oIFrameTemplate = document.createElement("iframe");
3034
if (this.isSecure) {
3035
m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
3039
Set the opacity of the <iframe> to 0 so that it
3040
doesn't modify the opacity of any transparent
3041
elements that may be on top of it (like a shadow).
3044
m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
3046
Need to set the "frameBorder" property to 0
3047
supress the default <iframe> border in IE.
3048
Setting the CSS "border" property alone
3051
m_oIFrameTemplate.frameBorder = 0;
3054
m_oIFrameTemplate.style.opacity = "0";
3057
m_oIFrameTemplate.style.position = "absolute";
3058
m_oIFrameTemplate.style.border = "none";
3059
m_oIFrameTemplate.style.margin = "0";
3060
m_oIFrameTemplate.style.padding = "0";
3061
m_oIFrameTemplate.style.display = "none";
3064
oIFrame = m_oIFrameTemplate.cloneNode(false);
3065
oParent = oElement.parentNode;
3067
var parentNode = oParent || document.body;
3069
this._addToParent(parentNode, oIFrame);
3070
this.iframe = oIFrame;
3074
Show the <iframe> before positioning it since the "setXY"
3075
method of DOM requires the element be in the document
3081
Syncronize the size and position of the <iframe> to that
3087
// Add event listeners to update the <iframe> when necessary
3088
if (!this._hasIframeEventListeners) {
3089
this.showEvent.subscribe(this.showIframe);
3090
this.hideEvent.subscribe(this.hideIframe);
3091
this.changeContentEvent.subscribe(this.syncIframe);
3093
this._hasIframeEventListeners = true;
3097
function onBeforeShow() {
3098
createIFrame.call(this);
3099
this.beforeShowEvent.unsubscribe(onBeforeShow);
3100
this._iframeDeferred = false;
3103
if (bIFrame) { // <iframe> shim is enabled
3105
if (this.cfg.getProperty("visible")) {
3106
createIFrame.call(this);
3108
if (!this._iframeDeferred) {
3109
this.beforeShowEvent.subscribe(onBeforeShow);
3110
this._iframeDeferred = true;
3114
} else { // <iframe> shim is disabled
3117
if (this._hasIframeEventListeners) {
3118
this.showEvent.unsubscribe(this.showIframe);
3119
this.hideEvent.unsubscribe(this.hideIframe);
3120
this.changeContentEvent.unsubscribe(this.syncIframe);
3122
this._hasIframeEventListeners = false;
3128
* Set's the container's XY value from DOM if not already set.
3130
* Differs from syncPosition, in that the XY value is only sync'd with DOM if
3131
* not already set. The method also refire's the XY config property event, so any
3132
* beforeMove, Move event listeners are invoked.
3134
* @method _primeXYFromDOM
3137
_primeXYFromDOM : function() {
3138
if (YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))) {
3139
// Set CFG XY based on DOM XY
3140
this.syncPosition();
3141
// Account for XY being set silently in syncPosition (no moveTo fired/called)
3142
this.cfg.refireEvent("xy");
3143
this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3148
* The default event handler fired when the "constraintoviewport"
3149
* property is changed.
3150
* @method configConstrainToViewport
3151
* @param {String} type The CustomEvent type (usually the property name)
3152
* @param {Object[]} args The CustomEvent arguments. For configuration
3153
* handlers, args[0] will equal the newly applied value for
3155
* @param {Object} obj The scope object. For configuration handlers,
3156
* this will usually equal the owner.
3158
configConstrainToViewport: function (type, args, obj) {
3162
if (! Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
3163
this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
3165
if (! Config.alreadySubscribed(this.beforeShowEvent, this._primeXYFromDOM)) {
3166
this.beforeShowEvent.subscribe(this._primeXYFromDOM);
3169
this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3170
this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
3175
* The default event handler fired when the "context" property
3178
* @method configContext
3179
* @param {String} type The CustomEvent type (usually the property name)
3180
* @param {Object[]} args The CustomEvent arguments. For configuration
3181
* handlers, args[0] will equal the newly applied value for the property.
3182
* @param {Object} obj The scope object. For configuration handlers,
3183
* this will usually equal the owner.
3185
configContext: function (type, args, obj) {
3187
var contextArgs = args[0],
3189
elementMagnetCorner,
3190
contextMagnetCorner,
3192
defTriggers = this.CONTEXT_TRIGGERS;
3196
contextEl = contextArgs[0];
3197
elementMagnetCorner = contextArgs[1];
3198
contextMagnetCorner = contextArgs[2];
3199
triggers = contextArgs[3];
3201
if (defTriggers && defTriggers.length > 0) {
3202
triggers = (triggers || []).concat(defTriggers);
3206
if (typeof contextEl == "string") {
3207
this.cfg.setProperty("context", [
3208
document.getElementById(contextEl),
3209
elementMagnetCorner,
3210
contextMagnetCorner,
3215
if (elementMagnetCorner && contextMagnetCorner) {
3216
this.align(elementMagnetCorner, contextMagnetCorner);
3219
if (this._contextTriggers) {
3220
// Unsubscribe Old Set
3221
this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
3225
// Subscribe New Set
3226
this._processTriggers(triggers, _SUBSCRIBE, this._alignOnTrigger);
3227
this._contextTriggers = triggers;
3234
* Custom Event handler for context alignment triggers. Invokes the align method
3236
* @method _alignOnTrigger
3239
* @param {String} type The event type (not used by the default implementation)
3240
* @param {Any[]} args The array of arguments for the trigger event (not used by the default implementation)
3242
_alignOnTrigger: function(type, args) {
3247
* Helper method to locate the custom event instance for the event name string
3248
* passed in. As a convenience measure, any custom events passed in are returned.
3250
* @method _findTriggerCE
3253
* @param {String|CustomEvent} t Either a CustomEvent, or event type (e.g. "windowScroll") for which a
3254
* custom event instance needs to be looked up from the Overlay._TRIGGER_MAP.
3256
_findTriggerCE : function(t) {
3258
if (t instanceof CustomEvent) {
3260
} else if (Overlay._TRIGGER_MAP[t]) {
3261
tce = Overlay._TRIGGER_MAP[t];
3267
* Utility method that subscribes or unsubscribes the given
3268
* function from the list of trigger events provided.
3270
* @method _processTriggers
3273
* @param {Array[String|CustomEvent]} triggers An array of either CustomEvents, event type strings
3274
* (e.g. "beforeShow", "windowScroll") to/from which the provided function should be
3275
* subscribed/unsubscribed respectively.
3277
* @param {String} mode Either "subscribe" or "unsubscribe", specifying whether or not
3278
* we are subscribing or unsubscribing trigger listeners
3280
* @param {Function} fn The function to be subscribed/unsubscribed to/from the trigger event.
3281
* Context is always set to the overlay instance, and no additional object argument
3282
* get passed to the subscribed function.
3284
_processTriggers : function(triggers, mode, fn) {
3287
for (var i = 0, l = triggers.length; i < l; ++i) {
3289
tce = this._findTriggerCE(t);
3291
tce[mode](fn, this, true);
3298
// END BUILT-IN PROPERTY EVENT HANDLERS //
3300
* Aligns the Overlay to its context element using the specified corner
3301
* points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT,
3304
* @param {String} elementAlign The String representing the corner of
3305
* the Overlay that should be aligned to the context element
3306
* @param {String} contextAlign The corner of the context element
3307
* that the elementAlign corner should stick to.
3309
align: function (elementAlign, contextAlign) {
3311
var contextArgs = this.cfg.getProperty("context"),
3317
function doAlign(v, h) {
3319
switch (elementAlign) {
3321
case Overlay.TOP_LEFT:
3325
case Overlay.TOP_RIGHT:
3326
me.moveTo((h - element.offsetWidth), v);
3329
case Overlay.BOTTOM_LEFT:
3330
me.moveTo(h, (v - element.offsetHeight));
3333
case Overlay.BOTTOM_RIGHT:
3334
me.moveTo((h - element.offsetWidth),
3335
(v - element.offsetHeight));
3343
context = contextArgs[0];
3344
element = this.element;
3347
if (! elementAlign) {
3348
elementAlign = contextArgs[1];
3351
if (! contextAlign) {
3352
contextAlign = contextArgs[2];
3355
if (element && context) {
3356
contextRegion = Dom.getRegion(context);
3358
switch (contextAlign) {
3360
case Overlay.TOP_LEFT:
3361
doAlign(contextRegion.top, contextRegion.left);
3364
case Overlay.TOP_RIGHT:
3365
doAlign(contextRegion.top, contextRegion.right);
3368
case Overlay.BOTTOM_LEFT:
3369
doAlign(contextRegion.bottom, contextRegion.left);
3372
case Overlay.BOTTOM_RIGHT:
3373
doAlign(contextRegion.bottom, contextRegion.right);
3384
* The default event handler executed when the moveEvent is fired, if the
3385
* "constraintoviewport" is set to true.
3386
* @method enforceConstraints
3387
* @param {String} type The CustomEvent type (usually the property name)
3388
* @param {Object[]} args The CustomEvent arguments. For configuration
3389
* handlers, args[0] will equal the newly applied value for the property.
3390
* @param {Object} obj The scope object. For configuration handlers,
3391
* this will usually equal the owner.
3393
enforceConstraints: function (type, args, obj) {
3396
var cXY = this.getConstrainedXY(pos[0], pos[1]);
3397
this.cfg.setProperty("x", cXY[0], true);
3398
this.cfg.setProperty("y", cXY[1], true);
3399
this.cfg.setProperty("xy", cXY, true);
3404
* Given x coordinate value, returns the calculated x coordinate required to
3405
* position the Overlay if it is to be constrained to the viewport, based on the
3406
* current element size, viewport dimensions and scroll values.
3408
* @param {Number} x The X coordinate value to be constrained
3409
* @return {Number} The constrained x coordinate
3411
getConstrainedX: function (x) {
3413
var oOverlay = this,
3414
oOverlayEl = oOverlay.element,
3415
nOverlayOffsetWidth = oOverlayEl.offsetWidth,
3417
nViewportOffset = Overlay.VIEWPORT_OFFSET,
3418
viewPortWidth = Dom.getViewportWidth(),
3419
scrollX = Dom.getDocumentScrollLeft(),
3421
bCanConstrain = (nOverlayOffsetWidth + nViewportOffset < viewPortWidth),
3423
aContext = this.cfg.getProperty("context"),
3438
oOverlapPositions = {
3448
var flipHorizontal = function () {
3452
if ((oOverlay.cfg.getProperty("x") - scrollX) > nContextElX) {
3453
nNewX = (nContextElX - nOverlayOffsetWidth);
3456
nNewX = (nContextElX + nContextElWidth);
3460
oOverlay.cfg.setProperty("x", (nNewX + scrollX), true);
3469
Uses the context element's position to calculate the availble width
3470
to the right and left of it to display its corresponding Overlay.
3473
var getDisplayRegionWidth = function () {
3475
// The Overlay is to the right of the context element
3477
if ((oOverlay.cfg.getProperty("x") - scrollX) > nContextElX) {
3478
return (nRightRegionWidth - nViewportOffset);
3480
else { // The Overlay is to the left of the context element
3481
return (nLeftRegionWidth - nViewportOffset);
3488
Positions the Overlay to the left or right of the context element so that it remains
3489
inside the viewport.
3492
var setHorizontalPosition = function () {
3494
var nDisplayRegionWidth = getDisplayRegionWidth(),
3497
if (nOverlayOffsetWidth > nDisplayRegionWidth) {
3502
All possible positions and values have been
3503
tried, but none were successful, so fall back
3504
to the original size and position.
3516
fnReturnVal = setHorizontalPosition();
3527
if (this.cfg.getProperty("preventcontextoverlap") && aContext &&
3528
oOverlapPositions[(aContext[1] + aContext[2])]) {
3530
if (bCanConstrain) {
3532
oContextEl = aContext[0];
3533
nContextElX = Dom.getX(oContextEl) - scrollX;
3534
nContextElWidth = oContextEl.offsetWidth;
3535
nLeftRegionWidth = nContextElX;
3536
nRightRegionWidth = (viewPortWidth - (nContextElX + nContextElWidth));
3538
setHorizontalPosition();
3542
xNew = this.cfg.getProperty("x");
3547
if (bCanConstrain) {
3549
leftConstraint = scrollX + nViewportOffset;
3551
scrollX + viewPortWidth - nOverlayOffsetWidth - nViewportOffset;
3553
if (x < leftConstraint) {
3554
xNew = leftConstraint;
3555
} else if (x > rightConstraint) {
3556
xNew = rightConstraint;
3559
xNew = nViewportOffset + scrollX;
3570
* Given y coordinate value, returns the calculated y coordinate required to
3571
* position the Overlay if it is to be constrained to the viewport, based on the
3572
* current element size, viewport dimensions and scroll values.
3574
* @param {Number} y The Y coordinate value to be constrained
3575
* @return {Number} The constrained y coordinate
3577
getConstrainedY: function (y) {
3579
var oOverlay = this,
3580
oOverlayEl = oOverlay.element,
3581
nOverlayOffsetHeight = oOverlayEl.offsetHeight,
3583
nViewportOffset = Overlay.VIEWPORT_OFFSET,
3584
viewPortHeight = Dom.getViewportHeight(),
3585
scrollY = Dom.getDocumentScrollTop(),
3587
bCanConstrain = (nOverlayOffsetHeight + nViewportOffset < viewPortHeight),
3589
aContext = this.cfg.getProperty("context"),
3597
nBottomRegionHeight,
3604
oOverlapPositions = {
3612
var flipVertical = function () {
3616
// The Overlay is below the context element, flip it above
3617
if ((oOverlay.cfg.getProperty("y") - scrollY) > nContextElY) {
3618
nNewY = (nContextElY - nOverlayOffsetHeight);
3620
else { // The Overlay is above the context element, flip it below
3621
nNewY = (nContextElY + nContextElHeight);
3624
oOverlay.cfg.setProperty("y", (nNewY + scrollY), true);
3632
Uses the context element's position to calculate the availble height
3633
above and below it to display its corresponding Overlay.
3636
var getDisplayRegionHeight = function () {
3638
// The Overlay is below the context element
3639
if ((oOverlay.cfg.getProperty("y") - scrollY) > nContextElY) {
3640
return (nBottomRegionHeight - nViewportOffset);
3642
else { // The Overlay is above the context element
3643
return (nTopRegionHeight - nViewportOffset);
3650
Trys to place the Overlay in the best possible position (either above or
3651
below its corresponding context element).
3654
var setVerticalPosition = function () {
3656
var nDisplayRegionHeight = getDisplayRegionHeight(),
3660
if (nOverlayOffsetHeight > nDisplayRegionHeight) {
3665
All possible positions and values for the
3666
"maxheight" configuration property have been
3667
tried, but none were successful, so fall back
3668
to the original size and position.
3680
fnReturnVal = setVerticalPosition();
3691
if (this.cfg.getProperty("preventcontextoverlap") && aContext &&
3692
oOverlapPositions[(aContext[1] + aContext[2])]) {
3694
if (bCanConstrain) {
3696
oContextEl = aContext[0];
3697
nContextElHeight = oContextEl.offsetHeight;
3698
nContextElY = (Dom.getY(oContextEl) - scrollY);
3700
nTopRegionHeight = nContextElY;
3701
nBottomRegionHeight = (viewPortHeight - (nContextElY + nContextElHeight));
3703
setVerticalPosition();
3707
yNew = oOverlay.cfg.getProperty("y");
3712
if (bCanConstrain) {
3714
topConstraint = scrollY + nViewportOffset;
3716
scrollY + viewPortHeight - nOverlayOffsetHeight - nViewportOffset;
3718
if (y < topConstraint) {
3719
yNew = topConstraint;
3720
} else if (y > bottomConstraint) {
3721
yNew = bottomConstraint;
3724
yNew = nViewportOffset + scrollY;
3734
* Given x, y coordinate values, returns the calculated coordinates required to
3735
* position the Overlay if it is to be constrained to the viewport, based on the
3736
* current element size, viewport dimensions and scroll values.
3738
* @param {Number} x The X coordinate value to be constrained
3739
* @param {Number} y The Y coordinate value to be constrained
3740
* @return {Array} The constrained x and y coordinates at index 0 and 1 respectively;
3742
getConstrainedXY: function(x, y) {
3743
return [this.getConstrainedX(x), this.getConstrainedY(y)];
3747
* Centers the container in the viewport.
3750
center: function () {
3752
var nViewportOffset = Overlay.VIEWPORT_OFFSET,
3753
elementWidth = this.element.offsetWidth,
3754
elementHeight = this.element.offsetHeight,
3755
viewPortWidth = Dom.getViewportWidth(),
3756
viewPortHeight = Dom.getViewportHeight(),
3760
if (elementWidth < viewPortWidth) {
3761
x = (viewPortWidth / 2) - (elementWidth / 2) + Dom.getDocumentScrollLeft();
3763
x = nViewportOffset + Dom.getDocumentScrollLeft();
3766
if (elementHeight < viewPortHeight) {
3767
y = (viewPortHeight / 2) - (elementHeight / 2) + Dom.getDocumentScrollTop();
3769
y = nViewportOffset + Dom.getDocumentScrollTop();
3772
this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
3773
this.cfg.refireEvent("iframe");
3777
* Synchronizes the Panel's "xy", "x", and "y" properties with the
3778
* Panel's position in the DOM. This is primarily used to update
3779
* position information during drag & drop.
3780
* @method syncPosition
3782
syncPosition: function () {
3784
var pos = Dom.getXY(this.element);
3786
this.cfg.setProperty("x", pos[0], true);
3787
this.cfg.setProperty("y", pos[1], true);
3788
this.cfg.setProperty("xy", pos, true);
3793
* Event handler fired when the resize monitor element is resized.
3794
* @method onDomResize
3795
* @param {DOMEvent} e The resize DOM event
3796
* @param {Object} obj The scope object
3798
onDomResize: function (e, obj) {
3802
Overlay.superclass.onDomResize.call(this, e, obj);
3804
setTimeout(function () {
3806
me.cfg.refireEvent("iframe");
3807
me.cfg.refireEvent("context");
3812
* Determines the content box height of the given element (height of the element, without padding or borders) in pixels.
3814
* @method _getComputedHeight
3816
* @param {HTMLElement} el The element for which the content height needs to be determined
3817
* @return {Number} The content box height of the given element, or null if it could not be determined.
3819
_getComputedHeight : (function() {
3821
if (document.defaultView && document.defaultView.getComputedStyle) {
3822
return function(el) {
3824
if (el.ownerDocument && el.ownerDocument.defaultView) {
3825
var computed = el.ownerDocument.defaultView.getComputedStyle(el, '');
3827
height = parseInt(computed.height, 10);
3830
return (Lang.isNumber(height)) ? height : null;
3833
return function(el) {
3835
if (el.style.pixelHeight) {
3836
height = el.style.pixelHeight;
3838
return (Lang.isNumber(height)) ? height : null;
3844
* autofillheight validator. Verifies that the autofill value is either null
3845
* or one of the strings : "body", "header" or "footer".
3847
* @method _validateAutoFillHeight
3849
* @param {String} val
3850
* @return true, if valid, false otherwise
3852
_validateAutoFillHeight : function(val) {
3853
return (!val) || (Lang.isString(val) && Overlay.STD_MOD_RE.test(val));
3857
* The default custom event handler executed when the overlay's height is changed,
3858
* if the autofillheight property has been set.
3860
* @method _autoFillOnHeightChange
3862
* @param {String} type The event type
3863
* @param {Array} args The array of arguments passed to event subscribers
3864
* @param {HTMLElement} el The header, body or footer element which is to be resized to fill
3865
* out the containers height
3867
_autoFillOnHeightChange : function(type, args, el) {
3868
this.fillHeight(el);
3872
* Returns the sub-pixel height of the el, using getBoundingClientRect, if available,
3873
* otherwise returns the offsetHeight
3874
* @method _getPreciseHeight
3876
* @param {HTMLElement} el
3877
* @return {Float} The sub-pixel height if supported by the browser, else the rounded height.
3879
_getPreciseHeight : function(el) {
3880
var height = el.offsetHeight;
3882
if (el.getBoundingClientRect) {
3883
var rect = el.getBoundingClientRect();
3884
height = rect.bottom - rect.top;
3892
* Sets the height on the provided header, body or footer element to
3893
* fill out the height of the container. It determines the height of the
3894
* containers content box, based on it's configured height value, and
3895
* sets the height of the autofillheight element to fill out any
3896
* space remaining after the other standard module element heights
3897
* have been accounted for.
3899
* <p><strong>NOTE:</strong> This method is not designed to work if an explicit
3900
* height has not been set on the container, since for an "auto" height container,
3901
* the heights of the header/body/footer will drive the height of the container.</p>
3903
* @method fillHeight
3904
* @param {HTMLElement} el The element which should be resized to fill out the height
3905
* of the container element.
3907
fillHeight : function(el) {
3909
var container = this.innerElement || this.element,
3910
containerEls = [this.header, this.body, this.footer],
3917
for (var i = 0, l = containerEls.length; i < l; i++) {
3918
containerEl = containerEls[i];
3920
if (el !== containerEl) {
3921
filled += this._getPreciseHeight(containerEl);
3930
if (UA.ie || UA.opera) {
3931
// Need to set height to 0, to allow height to be reduced
3932
Dom.setStyle(el, 'height', 0 + 'px');
3935
total = this._getComputedHeight(container);
3937
// Fallback, if we can't get computed value for content height
3938
if (total === null) {
3939
Dom.addClass(container, "yui-override-padding");
3940
total = container.clientHeight; // Content, No Border, 0 Padding (set by yui-override-padding)
3941
Dom.removeClass(container, "yui-override-padding");
3944
remaining = total - filled;
3946
Dom.setStyle(el, "height", remaining + "px");
3948
// Re-adjust height if required, to account for el padding and border
3949
if (el.offsetHeight != remaining) {
3950
remaining = remaining - (el.offsetHeight - remaining);
3952
Dom.setStyle(el, "height", remaining + "px");
3958
* Places the Overlay on top of all other instances of
3959
* YAHOO.widget.Overlay.
3960
* @method bringToTop
3962
bringToTop: function () {
3965
oElement = this.element;
3967
function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
3969
var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
3970
sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
3972
nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 0 : parseInt(sZIndex1, 10),
3973
nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 0 : parseInt(sZIndex2, 10);
3975
if (nZIndex1 > nZIndex2) {
3977
} else if (nZIndex1 < nZIndex2) {
3984
function isOverlayElement(p_oElement) {
3986
var isOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
3987
Panel = YAHOO.widget.Panel;
3989
if (isOverlay && !Dom.isAncestor(oElement, p_oElement)) {
3990
if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
3991
aOverlays[aOverlays.length] = p_oElement.parentNode;
3993
aOverlays[aOverlays.length] = p_oElement;
3998
Dom.getElementsBy(isOverlayElement, "DIV", document.body);
4000
aOverlays.sort(compareZIndexDesc);
4002
var oTopOverlay = aOverlays[0],
4006
nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
4008
if (!isNaN(nTopZIndex)) {
4009
var bRequiresBump = false;
4011
if (oTopOverlay != oElement) {
4012
bRequiresBump = true;
4013
} else if (aOverlays.length > 1) {
4014
var nNextZIndex = Dom.getStyle(aOverlays[1], "zIndex");
4015
// Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4016
if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4017
bRequiresBump = true;
4020
if (bRequiresBump) {
4021
this.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4028
* Removes the Overlay element from the DOM and sets all child
4032
destroy: function () {
4035
this.iframe.parentNode.removeChild(this.iframe);
4040
Overlay.windowResizeEvent.unsubscribe(
4041
this.doCenterOnDOMEvent, this);
4043
Overlay.windowScrollEvent.unsubscribe(
4044
this.doCenterOnDOMEvent, this);
4046
Module.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);
4048
Overlay.superclass.destroy.call(this);
4052
* Returns a String representation of the object.
4054
* @return {String} The string representation of the Overlay.
4056
toString: function () {
4057
return "Overlay " + this.id;
4066
* OverlayManager is used for maintaining the focus status of
4067
* multiple Overlays.
4068
* @namespace YAHOO.widget
4069
* @namespace YAHOO.widget
4070
* @class OverlayManager
4072
* @param {Array} overlays Optional. A collection of Overlays to register
4074
* @param {Object} userConfig The object literal representing the user
4075
* configuration of the OverlayManager
4077
YAHOO.widget.OverlayManager = function (userConfig) {
4078
this.init(userConfig);
4081
var Overlay = YAHOO.widget.Overlay,
4082
Event = YAHOO.util.Event,
4083
Dom = YAHOO.util.Dom,
4084
Config = YAHOO.util.Config,
4085
CustomEvent = YAHOO.util.CustomEvent,
4086
OverlayManager = YAHOO.widget.OverlayManager;
4089
* The CSS class representing a focused Overlay
4090
* @property OverlayManager.CSS_FOCUSED
4095
OverlayManager.CSS_FOCUSED = "focused";
4097
OverlayManager.prototype = {
4100
* The class's constructor function
4101
* @property contructor
4104
constructor: OverlayManager,
4107
* The array of Overlays that are currently registered
4108
* @property overlays
4109
* @type YAHOO.widget.Overlay[]
4114
* Initializes the default configuration of the OverlayManager
4115
* @method initDefaultConfig
4117
initDefaultConfig: function () {
4119
* The collection of registered Overlays in use by
4120
* the OverlayManager
4122
* @type YAHOO.widget.Overlay[]
4125
this.cfg.addProperty("overlays", { suppressEvent: true } );
4128
* The default DOM event that should be used to focus an Overlay
4129
* @config focusevent
4131
* @default "mousedown"
4133
this.cfg.addProperty("focusevent", { value: "mousedown" } );
4137
* Initializes the OverlayManager
4139
* @param {Overlay[]} overlays Optional. A collection of Overlays to
4140
* register with the manager.
4141
* @param {Object} userConfig The object literal representing the user
4142
* configuration of the OverlayManager
4144
init: function (userConfig) {
4147
* The OverlayManager's Config object used for monitoring
4148
* configuration properties.
4152
this.cfg = new Config(this);
4154
this.initDefaultConfig();
4157
this.cfg.applyConfig(userConfig, true);
4159
this.cfg.fireQueue();
4162
* The currently activated Overlay
4163
* @property activeOverlay
4165
* @type YAHOO.widget.Overlay
4167
var activeOverlay = null;
4170
* Returns the currently focused Overlay
4172
* @return {Overlay} The currently focused Overlay
4174
this.getActive = function () {
4175
return activeOverlay;
4179
* Focuses the specified Overlay
4181
* @param {Overlay} overlay The Overlay to focus
4182
* @param {String} overlay The id of the Overlay to focus
4184
this.focus = function (overlay) {
4185
var o = this.find(overlay);
4192
* Removes the specified Overlay from the manager
4194
* @param {Overlay} overlay The Overlay to remove
4195
* @param {String} overlay The id of the Overlay to remove
4197
this.remove = function (overlay) {
4199
var o = this.find(overlay),
4203
if (activeOverlay == o) {
4204
activeOverlay = null;
4207
var bDestroyed = (o.element === null && o.cfg === null) ? true : false;
4210
// Set it's zindex so that it's sorted to the end.
4211
originalZ = Dom.getStyle(o.element, "zIndex");
4212
o.cfg.setProperty("zIndex", -1000, true);
4215
this.overlays.sort(this.compareZIndexDesc);
4216
this.overlays = this.overlays.slice(0, (this.overlays.length - 1));
4218
o.hideEvent.unsubscribe(o.blur);
4219
o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
4220
o.focusEvent.unsubscribe(this._onOverlayFocusHandler, o);
4221
o.blurEvent.unsubscribe(this._onOverlayBlurHandler, o);
4224
Event.removeListener(o.element, this.cfg.getProperty("focusevent"), this._onOverlayElementFocus);
4225
o.cfg.setProperty("zIndex", originalZ, true);
4226
o.cfg.setProperty("manager", null);
4229
/* _managed Flag for custom or existing. Don't want to remove existing */
4230
if (o.focusEvent._managed) { o.focusEvent = null; }
4231
if (o.blurEvent._managed) { o.blurEvent = null; }
4233
if (o.focus._managed) { o.focus = null; }
4234
if (o.blur._managed) { o.blur = null; }
4239
* Removes focus from all registered Overlays in the manager
4242
this.blurAll = function () {
4244
var nOverlays = this.overlays.length,
4247
if (nOverlays > 0) {
4250
this.overlays[i].blur();
4257
* Updates the state of the OverlayManager and overlay, as a result of the overlay
4260
* @method _manageBlur
4261
* @param {Overlay} overlay The overlay instance which got blurred.
4264
this._manageBlur = function (overlay) {
4265
var changed = false;
4266
if (activeOverlay == overlay) {
4267
Dom.removeClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4268
activeOverlay = null;
4275
* Updates the state of the OverlayManager and overlay, as a result of the overlay
4278
* @method _manageFocus
4279
* @param {Overlay} overlay The overlay instance which got focus.
4282
this._manageFocus = function(overlay) {
4283
var changed = false;
4284
if (activeOverlay != overlay) {
4285
if (activeOverlay) {
4286
activeOverlay.blur();
4288
activeOverlay = overlay;
4289
this.bringToTop(activeOverlay);
4290
Dom.addClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4296
var overlays = this.cfg.getProperty("overlays");
4298
if (! this.overlays) {
4303
this.register(overlays);
4304
this.overlays.sort(this.compareZIndexDesc);
4309
* @method _onOverlayElementFocus
4310
* @description Event handler for the DOM event that is used to focus
4311
* the Overlay instance as specified by the "focusevent"
4312
* configuration property.
4314
* @param {Event} p_oEvent Object representing the DOM event
4315
* object passed back by the event utility (Event).
4317
_onOverlayElementFocus: function (p_oEvent) {
4319
var oTarget = Event.getTarget(p_oEvent),
4320
oClose = this.close;
4322
if (oClose && (oTarget == oClose || Dom.isAncestor(oClose, oTarget))) {
4330
* @method _onOverlayDestroy
4331
* @description "destroy" event handler for the Overlay.
4333
* @param {String} p_sType String representing the name of the event
4335
* @param {Array} p_aArgs Array of arguments sent when the event
4337
* @param {Overlay} p_oOverlay Object representing the overlay that
4340
_onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
4341
this.remove(p_oOverlay);
4345
* @method _onOverlayFocusHandler
4347
* focusEvent Handler, used to delegate to _manageFocus with the
4348
* correct arguments.
4351
* @param {String} p_sType String representing the name of the event
4353
* @param {Array} p_aArgs Array of arguments sent when the event
4355
* @param {Overlay} p_oOverlay Object representing the overlay that
4358
_onOverlayFocusHandler: function(p_sType, p_aArgs, p_oOverlay) {
4359
this._manageFocus(p_oOverlay);
4363
* @method _onOverlayBlurHandler
4365
* blurEvent Handler, used to delegate to _manageBlur with the
4366
* correct arguments.
4369
* @param {String} p_sType String representing the name of the event
4371
* @param {Array} p_aArgs Array of arguments sent when the event
4373
* @param {Overlay} p_oOverlay Object representing the overlay that
4376
_onOverlayBlurHandler: function(p_sType, p_aArgs, p_oOverlay) {
4377
this._manageBlur(p_oOverlay);
4381
* Subscribes to the Overlay based instance focusEvent, to allow the OverlayManager to
4382
* monitor focus state.
4384
* If the instance already has a focusEvent (e.g. Menu), OverlayManager will subscribe
4385
* to the existing focusEvent, however if a focusEvent or focus method does not exist
4386
* on the instance, the _bindFocus method will add them, and the focus method will
4387
* update the OverlayManager's state directly.
4389
* @method _bindFocus
4390
* @param {Overlay} overlay The overlay for which focus needs to be managed
4393
_bindFocus : function(overlay) {
4396
if (!overlay.focusEvent) {
4397
overlay.focusEvent = overlay.createEvent("focus");
4398
overlay.focusEvent.signature = CustomEvent.LIST;
4399
overlay.focusEvent._managed = true;
4401
overlay.focusEvent.subscribe(mgr._onOverlayFocusHandler, overlay, mgr);
4404
if (!overlay.focus) {
4405
Event.on(overlay.element, mgr.cfg.getProperty("focusevent"), mgr._onOverlayElementFocus, null, overlay);
4406
overlay.focus = function () {
4407
if (mgr._manageFocus(this)) {
4409
if (this.cfg.getProperty("visible") && this.focusFirst) {
4412
this.focusEvent.fire();
4415
overlay.focus._managed = true;
4420
* Subscribes to the Overlay based instance's blurEvent to allow the OverlayManager to
4421
* monitor blur state.
4423
* If the instance already has a blurEvent (e.g. Menu), OverlayManager will subscribe
4424
* to the existing blurEvent, however if a blurEvent or blur method does not exist
4425
* on the instance, the _bindBlur method will add them, and the blur method
4426
* update the OverlayManager's state directly.
4429
* @param {Overlay} overlay The overlay for which blur needs to be managed
4432
_bindBlur : function(overlay) {
4435
if (!overlay.blurEvent) {
4436
overlay.blurEvent = overlay.createEvent("blur");
4437
overlay.blurEvent.signature = CustomEvent.LIST;
4438
overlay.focusEvent._managed = true;
4440
overlay.blurEvent.subscribe(mgr._onOverlayBlurHandler, overlay, mgr);
4443
if (!overlay.blur) {
4444
overlay.blur = function () {
4445
if (mgr._manageBlur(this)) {
4446
this.blurEvent.fire();
4449
overlay.blur._managed = true;
4452
overlay.hideEvent.subscribe(overlay.blur);
4456
* Subscribes to the Overlay based instance's destroyEvent, to allow the Overlay
4457
* to be removed for the OverlayManager when destroyed.
4459
* @method _bindDestroy
4460
* @param {Overlay} overlay The overlay instance being managed
4463
_bindDestroy : function(overlay) {
4465
overlay.destroyEvent.subscribe(mgr._onOverlayDestroy, overlay, mgr);
4469
* Ensures the zIndex configuration property on the managed overlay based instance
4470
* is set to the computed zIndex value from the DOM (with "auto" translating to 0).
4472
* @method _syncZIndex
4473
* @param {Overlay} overlay The overlay instance being managed
4476
_syncZIndex : function(overlay) {
4477
var zIndex = Dom.getStyle(overlay.element, "zIndex");
4478
if (!isNaN(zIndex)) {
4479
overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
4481
overlay.cfg.setProperty("zIndex", 0);
4486
* Registers an Overlay or an array of Overlays with the manager. Upon
4487
* registration, the Overlay receives functions for focus and blur,
4488
* along with CustomEvents for each.
4491
* @param {Overlay} overlay An Overlay to register with the manager.
4492
* @param {Overlay[]} overlay An array of Overlays to register with
4494
* @return {boolean} true if any Overlays are registered.
4496
register: function (overlay) {
4503
if (overlay instanceof Overlay) {
4505
overlay.cfg.addProperty("manager", { value: this } );
4507
this._bindFocus(overlay);
4508
this._bindBlur(overlay);
4509
this._bindDestroy(overlay);
4510
this._syncZIndex(overlay);
4512
this.overlays.push(overlay);
4513
this.bringToTop(overlay);
4517
} else if (overlay instanceof Array) {
4519
for (i = 0, n = overlay.length; i < n; i++) {
4520
registered = this.register(overlay[i]) || registered;
4529
* Places the specified Overlay instance on top of all other
4530
* Overlay instances.
4531
* @method bringToTop
4532
* @param {YAHOO.widget.Overlay} p_oOverlay Object representing an
4534
* @param {String} p_oOverlay String representing the id of an
4537
bringToTop: function (p_oOverlay) {
4539
var oOverlay = this.find(p_oOverlay),
4546
aOverlays = this.overlays;
4547
aOverlays.sort(this.compareZIndexDesc);
4549
oTopOverlay = aOverlays[0];
4552
nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
4554
if (!isNaN(nTopZIndex)) {
4556
var bRequiresBump = false;
4558
if (oTopOverlay !== oOverlay) {
4559
bRequiresBump = true;
4560
} else if (aOverlays.length > 1) {
4561
var nNextZIndex = Dom.getStyle(aOverlays[1].element, "zIndex");
4562
// Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4563
if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4564
bRequiresBump = true;
4568
if (bRequiresBump) {
4569
oOverlay.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4572
aOverlays.sort(this.compareZIndexDesc);
4578
* Attempts to locate an Overlay by instance or ID.
4580
* @param {Overlay} overlay An Overlay to locate within the manager
4581
* @param {String} overlay An Overlay id to locate within the manager
4582
* @return {Overlay} The requested Overlay, if found, or null if it
4583
* cannot be located.
4585
find: function (overlay) {
4587
var isInstance = overlay instanceof Overlay,
4588
overlays = this.overlays,
4589
n = overlays.length,
4594
if (isInstance || typeof overlay == "string") {
4595
for (i = n-1; i >= 0; i--) {
4597
if ((isInstance && (o === overlay)) || (o.id == overlay)) {
4608
* Used for sorting the manager's Overlays by z-index.
4609
* @method compareZIndexDesc
4611
* @return {Number} 0, 1, or -1, depending on where the Overlay should
4612
* fall in the stacking order.
4614
compareZIndexDesc: function (o1, o2) {
4616
var zIndex1 = (o1.cfg) ? o1.cfg.getProperty("zIndex") : null, // Sort invalid (destroyed)
4617
zIndex2 = (o2.cfg) ? o2.cfg.getProperty("zIndex") : null; // objects at bottom.
4619
if (zIndex1 === null && zIndex2 === null) {
4621
} else if (zIndex1 === null){
4623
} else if (zIndex2 === null) {
4625
} else if (zIndex1 > zIndex2) {
4627
} else if (zIndex1 < zIndex2) {
4635
* Shows all Overlays in the manager.
4638
showAll: function () {
4639
var overlays = this.overlays,
4640
n = overlays.length,
4643
for (i = n - 1; i >= 0; i--) {
4649
* Hides all Overlays in the manager.
4652
hideAll: function () {
4653
var overlays = this.overlays,
4654
n = overlays.length,
4657
for (i = n - 1; i >= 0; i--) {
4663
* Returns a string representation of the object.
4665
* @return {String} The string representation of the OverlayManager
4667
toString: function () {
4668
return "OverlayManager";
4676
* ContainerEffect encapsulates animation transitions that are executed when
4677
* an Overlay is shown or hidden.
4678
* @namespace YAHOO.widget
4679
* @class ContainerEffect
4681
* @param {YAHOO.widget.Overlay} overlay The Overlay that the animation
4682
* should be associated with
4683
* @param {Object} attrIn The object literal representing the animation
4684
* arguments to be used for the animate-in transition. The arguments for
4685
* this literal are: attributes(object, see YAHOO.util.Anim for description),
4686
* duration(Number), and method(i.e. Easing.easeIn).
4687
* @param {Object} attrOut The object literal representing the animation
4688
* arguments to be used for the animate-out transition. The arguments for
4689
* this literal are: attributes(object, see YAHOO.util.Anim for description),
4690
* duration(Number), and method(i.e. Easing.easeIn).
4691
* @param {HTMLElement} targetElement Optional. The target element that
4692
* should be animated during the transition. Defaults to overlay.element.
4693
* @param {class} Optional. The animation class to instantiate. Defaults to
4694
* YAHOO.util.Anim. Other options include YAHOO.util.Motion.
4696
YAHOO.widget.ContainerEffect = function (overlay, attrIn, attrOut, targetElement, animClass) {
4699
animClass = YAHOO.util.Anim;
4703
* The overlay to animate
4705
* @type YAHOO.widget.Overlay
4707
this.overlay = overlay;
4710
* The animation attributes to use when transitioning into view
4714
this.attrIn = attrIn;
4717
* The animation attributes to use when transitioning out of view
4721
this.attrOut = attrOut;
4724
* The target element to be animated
4725
* @property targetElement
4728
this.targetElement = targetElement || overlay.element;
4731
* The animation class to use for animating the overlay
4732
* @property animClass
4735
this.animClass = animClass;
4740
var Dom = YAHOO.util.Dom,
4741
CustomEvent = YAHOO.util.CustomEvent,
4742
ContainerEffect = YAHOO.widget.ContainerEffect;
4746
* A pre-configured ContainerEffect instance that can be used for fading
4747
* an overlay in and out.
4750
* @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
4751
* @param {Number} dur The duration of the animation
4752
* @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
4754
ContainerEffect.FADE = function (overlay, dur) {
4756
var Easing = YAHOO.util.Easing,
4758
attributes: {opacity:{from:0, to:1}},
4760
method: Easing.easeIn
4763
attributes: {opacity:{to:0}},
4765
method: Easing.easeOut
4767
fade = new ContainerEffect(overlay, fin, fout, overlay.element);
4769
fade.handleUnderlayStart = function() {
4770
var underlay = this.overlay.underlay;
4771
if (underlay && YAHOO.env.ua.ie) {
4772
var hasFilters = (underlay.filters && underlay.filters.length > 0);
4774
Dom.addClass(overlay.element, "yui-effect-fade");
4779
fade.handleUnderlayComplete = function() {
4780
var underlay = this.overlay.underlay;
4781
if (underlay && YAHOO.env.ua.ie) {
4782
Dom.removeClass(overlay.element, "yui-effect-fade");
4786
fade.handleStartAnimateIn = function (type, args, obj) {
4787
Dom.addClass(obj.overlay.element, "hide-select");
4789
if (!obj.overlay.underlay) {
4790
obj.overlay.cfg.refireEvent("underlay");
4793
obj.handleUnderlayStart();
4795
Dom.setStyle(obj.overlay.element, "visibility", "visible");
4796
Dom.setStyle(obj.overlay.element, "opacity", 0);
4799
fade.handleCompleteAnimateIn = function (type,args,obj) {
4800
Dom.removeClass(obj.overlay.element, "hide-select");
4802
if (obj.overlay.element.style.filter) {
4803
obj.overlay.element.style.filter = null;
4806
obj.handleUnderlayComplete();
4808
obj.overlay.cfg.refireEvent("iframe");
4809
obj.animateInCompleteEvent.fire();
4812
fade.handleStartAnimateOut = function (type, args, obj) {
4813
Dom.addClass(obj.overlay.element, "hide-select");
4814
obj.handleUnderlayStart();
4817
fade.handleCompleteAnimateOut = function (type, args, obj) {
4818
Dom.removeClass(obj.overlay.element, "hide-select");
4819
if (obj.overlay.element.style.filter) {
4820
obj.overlay.element.style.filter = null;
4822
Dom.setStyle(obj.overlay.element, "visibility", "hidden");
4823
Dom.setStyle(obj.overlay.element, "opacity", 1);
4825
obj.handleUnderlayComplete();
4827
obj.overlay.cfg.refireEvent("iframe");
4828
obj.animateOutCompleteEvent.fire();
4837
* A pre-configured ContainerEffect instance that can be used for sliding an
4838
* overlay in and out.
4841
* @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
4842
* @param {Number} dur The duration of the animation
4843
* @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
4845
ContainerEffect.SLIDE = function (overlay, dur) {
4846
var Easing = YAHOO.util.Easing,
4848
x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
4849
y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
4850
clientWidth = Dom.getClientWidth(),
4851
offsetWidth = overlay.element.offsetWidth,
4854
attributes: { points: { to: [x, y] } },
4856
method: Easing.easeIn
4860
attributes: { points: { to: [(clientWidth + 25), y] } },
4862
method: Easing.easeOut
4865
slide = new ContainerEffect(overlay, sin, sout, overlay.element, YAHOO.util.Motion);
4867
slide.handleStartAnimateIn = function (type,args,obj) {
4868
obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
4869
obj.overlay.element.style.top = y + "px";
4872
slide.handleTweenAnimateIn = function (type, args, obj) {
4874
var pos = Dom.getXY(obj.overlay.element),
4878
if (Dom.getStyle(obj.overlay.element, "visibility") ==
4879
"hidden" && currentX < x) {
4881
Dom.setStyle(obj.overlay.element, "visibility", "visible");
4885
obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
4886
obj.overlay.cfg.refireEvent("iframe");
4889
slide.handleCompleteAnimateIn = function (type, args, obj) {
4890
obj.overlay.cfg.setProperty("xy", [x, y], true);
4893
obj.overlay.cfg.refireEvent("iframe");
4894
obj.animateInCompleteEvent.fire();
4897
slide.handleStartAnimateOut = function (type, args, obj) {
4899
var vw = Dom.getViewportWidth(),
4900
pos = Dom.getXY(obj.overlay.element),
4903
obj.animOut.attributes.points.to = [(vw + 25), yso];
4906
slide.handleTweenAnimateOut = function (type, args, obj) {
4908
var pos = Dom.getXY(obj.overlay.element),
4912
obj.overlay.cfg.setProperty("xy", [xto, yto], true);
4913
obj.overlay.cfg.refireEvent("iframe");
4916
slide.handleCompleteAnimateOut = function (type, args, obj) {
4917
Dom.setStyle(obj.overlay.element, "visibility", "hidden");
4919
obj.overlay.cfg.setProperty("xy", [x, y]);
4920
obj.animateOutCompleteEvent.fire();
4927
ContainerEffect.prototype = {
4930
* Initializes the animation classes and events.
4935
this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
4936
this.beforeAnimateInEvent.signature = CustomEvent.LIST;
4938
this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
4939
this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
4941
this.animateInCompleteEvent = this.createEvent("animateInComplete");
4942
this.animateInCompleteEvent.signature = CustomEvent.LIST;
4944
this.animateOutCompleteEvent =
4945
this.createEvent("animateOutComplete");
4946
this.animateOutCompleteEvent.signature = CustomEvent.LIST;
4948
this.animIn = new this.animClass(this.targetElement,
4949
this.attrIn.attributes, this.attrIn.duration,
4950
this.attrIn.method);
4952
this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
4953
this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
4955
this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn,
4958
this.animOut = new this.animClass(this.targetElement,
4959
this.attrOut.attributes, this.attrOut.duration,
4960
this.attrOut.method);
4962
this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
4963
this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
4964
this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut,
4970
* Triggers the in-animation.
4973
animateIn: function () {
4974
this.beforeAnimateInEvent.fire();
4975
this.animIn.animate();
4979
* Triggers the out-animation.
4980
* @method animateOut
4982
animateOut: function () {
4983
this.beforeAnimateOutEvent.fire();
4984
this.animOut.animate();
4988
* The default onStart handler for the in-animation.
4989
* @method handleStartAnimateIn
4990
* @param {String} type The CustomEvent type
4991
* @param {Object[]} args The CustomEvent arguments
4992
* @param {Object} obj The scope object
4994
handleStartAnimateIn: function (type, args, obj) { },
4997
* The default onTween handler for the in-animation.
4998
* @method handleTweenAnimateIn
4999
* @param {String} type The CustomEvent type
5000
* @param {Object[]} args The CustomEvent arguments
5001
* @param {Object} obj The scope object
5003
handleTweenAnimateIn: function (type, args, obj) { },
5006
* The default onComplete handler for the in-animation.
5007
* @method handleCompleteAnimateIn
5008
* @param {String} type The CustomEvent type
5009
* @param {Object[]} args The CustomEvent arguments
5010
* @param {Object} obj The scope object
5012
handleCompleteAnimateIn: function (type, args, obj) { },
5015
* The default onStart handler for the out-animation.
5016
* @method handleStartAnimateOut
5017
* @param {String} type The CustomEvent type
5018
* @param {Object[]} args The CustomEvent arguments
5019
* @param {Object} obj The scope object
5021
handleStartAnimateOut: function (type, args, obj) { },
5024
* The default onTween handler for the out-animation.
5025
* @method handleTweenAnimateOut
5026
* @param {String} type The CustomEvent type
5027
* @param {Object[]} args The CustomEvent arguments
5028
* @param {Object} obj The scope object
5030
handleTweenAnimateOut: function (type, args, obj) { },
5033
* The default onComplete handler for the out-animation.
5034
* @method handleCompleteAnimateOut
5035
* @param {String} type The CustomEvent type
5036
* @param {Object[]} args The CustomEvent arguments
5037
* @param {Object} obj The scope object
5039
handleCompleteAnimateOut: function (type, args, obj) { },
5042
* Returns a string representation of the object.
5044
* @return {String} The string representation of the ContainerEffect
5046
toString: function () {
5047
var output = "ContainerEffect";
5049
output += " [" + this.overlay.toString() + "]";
5055
YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
5059
YAHOO.register("containercore", YAHOO.widget.Module, {version: "2.6.0", build: "1321"});