2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3
Code licensed under the BSD License:
4
http://developer.yahoo.net/yui/license.txt
10
* Config is a utility used within an Object to allow the implementer to
11
* maintain a list of local configuration properties and listen for changes
12
* to those properties dynamically using CustomEvent. The initial values are
13
* also maintained so that the configuration can be reset at any given point
14
* to its initial state.
15
* @namespace YAHOO.util
18
* @param {Object} owner The owner Object to which this Config Object belongs
20
YAHOO.util.Config = function (owner) {
30
var Lang = YAHOO.lang,
31
CustomEvent = YAHOO.util.CustomEvent,
32
Config = YAHOO.util.Config;
36
* Constant representing the CustomEvent type for the config changed event.
37
* @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
42
Config.CONFIG_CHANGED_EVENT = "configChanged";
45
* Constant representing the boolean type string
46
* @property YAHOO.util.Config.BOOLEAN_TYPE
51
Config.BOOLEAN_TYPE = "boolean";
56
* Object reference to the owner of this Config Object
63
* Boolean flag that specifies whether a queue is currently
65
* @property queueInProgress
68
queueInProgress: false,
71
* Maintains the local collection of configuration property objects and
72
* their specified values
80
* Maintains the local collection of configuration property objects as
81
* they were initially applied.
82
* This object is used when resetting a property.
83
* @property initialConfig
90
* Maintains the local, normalized CustomEvent queue
91
* @property eventQueue
98
* Custom Event, notifying subscribers when Config properties are set
99
* (setProperty is called without the silent flag
100
* @event configChangedEvent
102
configChangedEvent: null,
105
* Initializes the configuration Object and all of its local members.
107
* @param {Object} owner The owner Object to which this Config
110
init: function (owner) {
114
this.configChangedEvent =
115
this.createEvent(Config.CONFIG_CHANGED_EVENT);
117
this.configChangedEvent.signature = CustomEvent.LIST;
118
this.queueInProgress = false;
120
this.initialConfig = {};
121
this.eventQueue = [];
126
* Validates that the value passed in is a Boolean.
127
* @method checkBoolean
128
* @param {Object} val The value to validate
129
* @return {Boolean} true, if the value is valid
131
checkBoolean: function (val) {
132
return (typeof val == Config.BOOLEAN_TYPE);
136
* Validates that the value passed in is a number.
137
* @method checkNumber
138
* @param {Object} val The value to validate
139
* @return {Boolean} true, if the value is valid
141
checkNumber: function (val) {
142
return (!isNaN(val));
146
* Fires a configuration property event using the specified value.
149
* @param {String} key The configuration property's name
150
* @param {value} Object The value of the correct type for the property
152
fireEvent: function ( key, value ) {
153
var property = this.config[key];
155
if (property && property.event) {
156
property.event.fire(value);
161
* Adds a property to the Config Object's private config hash.
162
* @method addProperty
163
* @param {String} key The configuration property's name
164
* @param {Object} propertyObject The Object containing all of this
165
* property's arguments
167
addProperty: function ( key, propertyObject ) {
168
key = key.toLowerCase();
170
this.config[key] = propertyObject;
172
propertyObject.event = this.createEvent(key, { scope: this.owner });
173
propertyObject.event.signature = CustomEvent.LIST;
176
propertyObject.key = key;
178
if (propertyObject.handler) {
179
propertyObject.event.subscribe(propertyObject.handler,
183
this.setProperty(key, propertyObject.value, true);
185
if (! propertyObject.suppressEvent) {
186
this.queueProperty(key, propertyObject.value);
192
* Returns a key-value configuration map of the values currently set in
195
* @return {Object} The current config, represented in a key-value map
197
getConfig: function () {
203
for (prop in this.config) {
204
property = this.config[prop];
205
if (property && property.event) {
206
cfg[prop] = property.value;
214
* Returns the value of specified property.
215
* @method getProperty
216
* @param {String} key The name of the property
217
* @return {Object} The value of the specified property
219
getProperty: function (key) {
220
var property = this.config[key.toLowerCase()];
221
if (property && property.event) {
222
return property.value;
229
* Resets the specified property's value to its initial value.
230
* @method resetProperty
231
* @param {String} key The name of the property
232
* @return {Boolean} True is the property was reset, false if not
234
resetProperty: function (key) {
236
key = key.toLowerCase();
238
var property = this.config[key];
240
if (property && property.event) {
242
if (this.initialConfig[key] &&
243
!Lang.isUndefined(this.initialConfig[key])) {
245
this.setProperty(key, this.initialConfig[key]);
259
* Sets the value of a property. If the silent property is passed as
260
* true, the property's event will not be fired.
261
* @method setProperty
262
* @param {String} key The name of the property
263
* @param {String} value The value to set the property to
264
* @param {Boolean} silent Whether the value should be set silently,
265
* without firing the property event.
266
* @return {Boolean} True, if the set was successful, false if it failed.
268
setProperty: function (key, value, silent) {
272
key = key.toLowerCase();
274
if (this.queueInProgress && ! silent) {
275
// Currently running through a queue...
276
this.queueProperty(key,value);
280
property = this.config[key];
281
if (property && property.event) {
282
if (property.validator && !property.validator(value)) {
285
property.value = value;
287
this.fireEvent(key, value);
288
this.configChangedEvent.fire([key, value]);
299
* Sets the value of a property and queues its event to execute. If the
300
* event is already scheduled to execute, it is
301
* moved from its current position to the end of the queue.
302
* @method queueProperty
303
* @param {String} key The name of the property
304
* @param {String} value The value to set the property to
305
* @return {Boolean} true, if the set was successful, false if
308
queueProperty: function (key, value) {
310
key = key.toLowerCase();
312
var property = this.config[key],
313
foundDuplicate = false,
328
if (property && property.event) {
330
if (!Lang.isUndefined(value) && property.validator &&
331
!property.validator(value)) { // validator
335
if (!Lang.isUndefined(value)) {
336
property.value = value;
338
value = property.value;
341
foundDuplicate = false;
342
iLen = this.eventQueue.length;
344
for (i = 0; i < iLen; i++) {
345
queueItem = this.eventQueue[i];
348
queueItemKey = queueItem[0];
349
queueItemValue = queueItem[1];
351
if (queueItemKey == key) {
354
found a dupe... push to end of queue, null
355
current item, and break
358
this.eventQueue[i] = null;
360
this.eventQueue.push(
361
[key, (!Lang.isUndefined(value) ?
362
value : queueItemValue)]);
364
foundDuplicate = true;
370
// this is a refire, or a new property in the queue
372
if (! foundDuplicate && !Lang.isUndefined(value)) {
373
this.eventQueue.push([key, value]);
377
if (property.supercedes) {
379
sLen = property.supercedes.length;
381
for (s = 0; s < sLen; s++) {
383
supercedesCheck = property.supercedes[s];
384
qLen = this.eventQueue.length;
386
for (q = 0; q < qLen; q++) {
387
queueItemCheck = this.eventQueue[q];
389
if (queueItemCheck) {
390
queueItemCheckKey = queueItemCheck[0];
391
queueItemCheckValue = queueItemCheck[1];
393
if (queueItemCheckKey ==
394
supercedesCheck.toLowerCase() ) {
396
this.eventQueue.push([queueItemCheckKey,
397
queueItemCheckValue]);
399
this.eventQueue[q] = null;
416
* Fires the event for a property using the property's current value.
417
* @method refireEvent
418
* @param {String} key The name of the property
420
refireEvent: function (key) {
422
key = key.toLowerCase();
424
var property = this.config[key];
426
if (property && property.event &&
428
!Lang.isUndefined(property.value)) {
430
if (this.queueInProgress) {
432
this.queueProperty(key);
436
this.fireEvent(key, property.value);
444
* Applies a key-value Object literal to the configuration, replacing
445
* any existing values, and queueing the property events.
446
* Although the values will be set, fireQueue() must be called for their
447
* associated events to execute.
448
* @method applyConfig
449
* @param {Object} userConfig The configuration Object literal
450
* @param {Boolean} init When set to true, the initialConfig will
451
* be set to the userConfig passed in, so that calling a reset will
452
* reset the properties to the passed values.
454
applyConfig: function (userConfig, init) {
461
for (sKey in userConfig) {
462
if (Lang.hasOwnProperty(userConfig, sKey)) {
463
oConfig[sKey.toLowerCase()] = userConfig[sKey];
466
this.initialConfig = oConfig;
469
for (sKey in userConfig) {
470
if (Lang.hasOwnProperty(userConfig, sKey)) {
471
this.queueProperty(sKey, userConfig[sKey]);
477
* Refires the events for all configuration properties using their
481
refresh: function () {
485
for (prop in this.config) {
486
this.refireEvent(prop);
491
* Fires the normalized list of queued property change events
494
fireQueue: function () {
502
this.queueInProgress = true;
503
for (i = 0;i < this.eventQueue.length; i++) {
504
queueItem = this.eventQueue[i];
508
value = queueItem[1];
509
property = this.config[key];
511
property.value = value;
513
this.fireEvent(key,value);
517
this.queueInProgress = false;
518
this.eventQueue = [];
522
* Subscribes an external handler to the change event for any
524
* @method subscribeToConfigEvent
525
* @param {String} key The property name
526
* @param {Function} handler The handler function to use subscribe to
527
* the property's event
528
* @param {Object} obj The Object to use for scoping the event handler
529
* (see CustomEvent documentation)
530
* @param {Boolean} override Optional. If true, will override "this"
531
* within the handler to map to the scope Object passed into the method.
532
* @return {Boolean} True, if the subscription was successful,
535
subscribeToConfigEvent: function (key, handler, obj, override) {
537
var property = this.config[key.toLowerCase()];
539
if (property && property.event) {
540
if (!Config.alreadySubscribed(property.event, handler, obj)) {
541
property.event.subscribe(handler, obj, override);
551
* Unsubscribes an external handler from the change event for any
553
* @method unsubscribeFromConfigEvent
554
* @param {String} key The property name
555
* @param {Function} handler The handler function to use subscribe to
556
* the property's event
557
* @param {Object} obj The Object to use for scoping the event
558
* handler (see CustomEvent documentation)
559
* @return {Boolean} True, if the unsubscription was successful,
562
unsubscribeFromConfigEvent: function (key, handler, obj) {
563
var property = this.config[key.toLowerCase()];
564
if (property && property.event) {
565
return property.event.unsubscribe(handler, obj);
572
* Returns a string representation of the Config object
574
* @return {String} The Config object in string format.
576
toString: function () {
577
var output = "Config";
579
output += " [" + this.owner.toString() + "]";
585
* Returns a string representation of the Config object's current
587
* @method outputEventQueue
588
* @return {String} The string list of CustomEvents currently queued
591
outputEventQueue: function () {
596
nQueue = this.eventQueue.length;
598
for (q = 0; q < nQueue; q++) {
599
queueItem = this.eventQueue[q];
601
output += queueItem[0] + "=" + queueItem[1] + ", ";
608
* Sets all properties to null, unsubscribes all listeners from each
609
* property's change event and all listeners from the configChangedEvent.
612
destroy: function () {
614
var oConfig = this.config,
619
for (sProperty in oConfig) {
621
if (Lang.hasOwnProperty(oConfig, sProperty)) {
623
oProperty = oConfig[sProperty];
625
oProperty.event.unsubscribeAll();
626
oProperty.event = null;
632
this.configChangedEvent.unsubscribeAll();
634
this.configChangedEvent = null;
637
this.initialConfig = null;
638
this.eventQueue = null;
647
* Checks to determine if a particular function/Object pair are already
648
* subscribed to the specified CustomEvent
649
* @method YAHOO.util.Config.alreadySubscribed
651
* @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check
653
* @param {Function} fn The function to look for in the subscribers list
654
* @param {Object} obj The execution scope Object for the subscription
655
* @return {Boolean} true, if the function/Object pair is already subscribed
656
* to the CustomEvent passed in
658
Config.alreadySubscribed = function (evt, fn, obj) {
660
var nSubscribers = evt.subscribers.length,
664
if (nSubscribers > 0) {
665
i = nSubscribers - 1;
667
subsc = evt.subscribers[i];
668
if (subsc && subsc.obj == obj && subsc.fn == fn) {
679
YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
686
* The Container family of components is designed to enable developers to
687
* create different kinds of content-containing modules on the web. Module
688
* and Overlay are the most basic containers, and they can be used directly
689
* or extended to build custom containers. Also part of the Container family
690
* are four UI controls that extend Module and Overlay: Tooltip, Panel,
691
* Dialog, and SimpleDialog.
694
* @requires yahoo, dom, event
695
* @optional dragdrop, animation, button
699
* Module is a JavaScript representation of the Standard Module Format.
700
* Standard Module Format is a simple standard for markup containers where
701
* child nodes representing the header, body, and footer of the content are
702
* denoted using the CSS classes "hd", "bd", and "ft" respectively.
703
* Module is the base class for all other classes in the YUI
705
* @namespace YAHOO.widget
708
* @param {String} el The element ID representing the Module <em>OR</em>
709
* @param {HTMLElement} el The element representing the Module
710
* @param {Object} userConfig The configuration Object literal containing
711
* the configuration that should be set for this module. See configuration
712
* documentation for more details.
714
YAHOO.widget.Module = function (el, userConfig) {
716
this.init(el, userConfig);
721
var Dom = YAHOO.util.Dom,
722
Config = YAHOO.util.Config,
723
Event = YAHOO.util.Event,
724
CustomEvent = YAHOO.util.CustomEvent,
725
Module = YAHOO.widget.Module,
733
* Constant representing the name of the Module's events
734
* @property EVENT_TYPES
741
"BEFORE_INIT": "beforeInit",
744
"BEFORE_RENDER": "beforeRender",
746
"CHANGE_HEADER": "changeHeader",
747
"CHANGE_BODY": "changeBody",
748
"CHANGE_FOOTER": "changeFooter",
749
"CHANGE_CONTENT": "changeContent",
750
"DESTORY": "destroy",
751
"BEFORE_SHOW": "beforeShow",
753
"BEFORE_HIDE": "beforeHide",
759
* Constant representing the Module's configuration properties
760
* @property DEFAULT_CONFIG
770
validator: YAHOO.lang.isBoolean
776
supercedes: ["visible"]
780
key: "monitorresize",
784
"APPEND_TO_DOCUMENT_BODY": {
785
key: "appendtodocumentbody",
791
* Constant representing the prefix path to use for non-secure images
792
* @property YAHOO.widget.Module.IMG_ROOT
797
Module.IMG_ROOT = null;
800
* Constant representing the prefix path to use for securely served images
801
* @property YAHOO.widget.Module.IMG_ROOT_SSL
806
Module.IMG_ROOT_SSL = null;
809
* Constant for the default CSS class name that represents a Module
810
* @property YAHOO.widget.Module.CSS_MODULE
815
Module.CSS_MODULE = "yui-module";
818
* Constant representing the module header
819
* @property YAHOO.widget.Module.CSS_HEADER
824
Module.CSS_HEADER = "hd";
827
* Constant representing the module body
828
* @property YAHOO.widget.Module.CSS_BODY
833
Module.CSS_BODY = "bd";
836
* Constant representing the module footer
837
* @property YAHOO.widget.Module.CSS_FOOTER
842
Module.CSS_FOOTER = "ft";
845
* Constant representing the url for the "src" attribute of the iframe
846
* used to monitor changes to the browser's base font size
847
* @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
852
Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
855
* Singleton CustomEvent fired when the font size is changed in the browser.
856
* Opera's "zoom" functionality currently does not support text
858
* @event YAHOO.widget.Module.textResizeEvent
860
Module.textResizeEvent = new CustomEvent("textResize");
862
function createModuleTemplate() {
864
if (!m_oModuleTemplate) {
865
m_oModuleTemplate = document.createElement("div");
867
m_oModuleTemplate.innerHTML = ("<div class=\"" +
868
Module.CSS_HEADER + "\"></div>" + "<div class=\"" +
869
Module.CSS_BODY + "\"></div><div class=\"" +
870
Module.CSS_FOOTER + "\"></div>");
872
m_oHeaderTemplate = m_oModuleTemplate.firstChild;
873
m_oBodyTemplate = m_oHeaderTemplate.nextSibling;
874
m_oFooterTemplate = m_oBodyTemplate.nextSibling;
877
return m_oModuleTemplate;
880
function createHeader() {
881
if (!m_oHeaderTemplate) {
882
createModuleTemplate();
884
return (m_oHeaderTemplate.cloneNode(false));
887
function createBody() {
888
if (!m_oBodyTemplate) {
889
createModuleTemplate();
891
return (m_oBodyTemplate.cloneNode(false));
894
function createFooter() {
895
if (!m_oFooterTemplate) {
896
createModuleTemplate();
898
return (m_oFooterTemplate.cloneNode(false));
904
* The class's constructor function
905
* @property contructor
911
* The main module element that contains the header, body, and footer
918
* The header element, denoted with CSS class "hd"
925
* The body element, denoted with CSS class "bd"
932
* The footer element, denoted with CSS class "ft"
939
* The id of the element
946
* A string representing the root path for all images created by
948
* @deprecated It is recommend that any images for a Module be applied
949
* via CSS using the "background-image" property.
950
* @property imageRoot
953
imageRoot: Module.IMG_ROOT,
956
* Initializes the custom events for Module which are fired
957
* automatically at appropriate times by the Module class.
960
initEvents: function () {
962
var SIGNATURE = CustomEvent.LIST;
965
* CustomEvent fired prior to class initalization.
966
* @event beforeInitEvent
967
* @param {class} classRef class reference of the initializing
968
* class, such as this.beforeInitEvent.fire(Module)
970
this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT);
971
this.beforeInitEvent.signature = SIGNATURE;
974
* CustomEvent fired after class initalization.
976
* @param {class} classRef class reference of the initializing
977
* class, such as this.beforeInitEvent.fire(Module)
979
this.initEvent = this.createEvent(EVENT_TYPES.INIT);
980
this.initEvent.signature = SIGNATURE;
983
* CustomEvent fired when the Module is appended to the DOM
986
this.appendEvent = this.createEvent(EVENT_TYPES.APPEND);
987
this.appendEvent.signature = SIGNATURE;
990
* CustomEvent fired before the Module is rendered
991
* @event beforeRenderEvent
993
this.beforeRenderEvent = this.createEvent(EVENT_TYPES.BEFORE_RENDER);
994
this.beforeRenderEvent.signature = SIGNATURE;
997
* CustomEvent fired after the Module is rendered
1000
this.renderEvent = this.createEvent(EVENT_TYPES.RENDER);
1001
this.renderEvent.signature = SIGNATURE;
1004
* CustomEvent fired when the header content of the Module
1006
* @event changeHeaderEvent
1007
* @param {String/HTMLElement} content String/element representing
1008
* the new header content
1010
this.changeHeaderEvent = this.createEvent(EVENT_TYPES.CHANGE_HEADER);
1011
this.changeHeaderEvent.signature = SIGNATURE;
1014
* CustomEvent fired when the body content of the Module is modified
1015
* @event changeBodyEvent
1016
* @param {String/HTMLElement} content String/element representing
1017
* the new body content
1019
this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY);
1020
this.changeBodyEvent.signature = SIGNATURE;
1023
* CustomEvent fired when the footer content of the Module
1025
* @event changeFooterEvent
1026
* @param {String/HTMLElement} content String/element representing
1027
* the new footer content
1029
this.changeFooterEvent = this.createEvent(EVENT_TYPES.CHANGE_FOOTER);
1030
this.changeFooterEvent.signature = SIGNATURE;
1033
* CustomEvent fired when the content of the Module is modified
1034
* @event changeContentEvent
1036
this.changeContentEvent = this.createEvent(EVENT_TYPES.CHANGE_CONTENT);
1037
this.changeContentEvent.signature = SIGNATURE;
1040
* CustomEvent fired when the Module is destroyed
1041
* @event destroyEvent
1043
this.destroyEvent = this.createEvent(EVENT_TYPES.DESTORY);
1044
this.destroyEvent.signature = SIGNATURE;
1047
* CustomEvent fired before the Module is shown
1048
* @event beforeShowEvent
1050
this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW);
1051
this.beforeShowEvent.signature = SIGNATURE;
1054
* CustomEvent fired after the Module is shown
1057
this.showEvent = this.createEvent(EVENT_TYPES.SHOW);
1058
this.showEvent.signature = SIGNATURE;
1061
* CustomEvent fired before the Module is hidden
1062
* @event beforeHideEvent
1064
this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE);
1065
this.beforeHideEvent.signature = SIGNATURE;
1068
* CustomEvent fired after the Module is hidden
1071
this.hideEvent = this.createEvent(EVENT_TYPES.HIDE);
1072
this.hideEvent.signature = SIGNATURE;
1076
* String representing the current user-agent platform
1077
* @property platform
1080
platform: function () {
1081
var ua = navigator.userAgent.toLowerCase();
1083
if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
1085
} else if (ua.indexOf("macintosh") != -1) {
1093
* String representing the user-agent of the browser
1094
* @deprecated Use YAHOO.env.ua
1098
browser: function () {
1099
var ua = navigator.userAgent.toLowerCase();
1101
Check Opera first in case of spoof and check Safari before
1102
Gecko since Safari's user agent string includes "like Gecko"
1104
if (ua.indexOf('opera') != -1) {
1106
} else if (ua.indexOf('msie 7') != -1) {
1108
} else if (ua.indexOf('msie') != -1) {
1110
} else if (ua.indexOf('safari') != -1) {
1112
} else if (ua.indexOf('gecko') != -1) {
1120
* Boolean representing whether or not the current browsing context is
1122
* @property isSecure
1125
isSecure: function () {
1126
if (window.location.href.toLowerCase().indexOf("https") === 0) {
1134
* Initializes the custom events for Module which are fired
1135
* automatically at appropriate times by the Module class.
1137
initDefaultConfig: function () {
1138
// Add properties //
1140
* Specifies whether the Module is visible on the page.
1145
this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, {
1146
handler: this.configVisible,
1147
value: DEFAULT_CONFIG.VISIBLE.value,
1148
validator: DEFAULT_CONFIG.VISIBLE.validator
1152
* Object or array of objects representing the ContainerEffect
1153
* classes that are active for animating the container.
1158
this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, {
1159
suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent,
1160
supercedes: DEFAULT_CONFIG.EFFECT.supercedes
1164
* Specifies whether to create a special proxy iframe to monitor
1165
* for user font resizing in the document
1166
* @config monitorresize
1170
this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, {
1171
handler: this.configMonitorResize,
1172
value: DEFAULT_CONFIG.MONITOR_RESIZE.value
1176
* Specifies if the module should be rendered as the first child
1177
* of document.body or appended as the last child when render is called
1178
* with document.body as the "appendToNode".
1180
* Appending to the body while the DOM is still being constructed can
1181
* lead to Operation Aborted errors in IE hence this flag is set to
1185
* @config appendtodocumentbody
1189
this.cfg.addProperty(DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.key, {
1190
value: DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.value
1195
* The Module class's initialization method, which is executed for
1196
* Module and all of its subclasses. This method is automatically
1197
* called by the constructor, and sets up all DOM references for
1198
* pre-existing markup, and creates required markup if it is not
1201
* @param {String} el The element ID representing the Module <em>OR</em>
1202
* @param {HTMLElement} el The element representing the Module
1203
* @param {Object} userConfig The configuration Object literal
1204
* containing the configuration that should be set for this module.
1205
* See configuration documentation for more details.
1207
init: function (el, userConfig) {
1212
this.beforeInitEvent.fire(Module);
1215
* The Module's Config object used for monitoring
1216
* configuration properties.
1218
* @type YAHOO.util.Config
1220
this.cfg = new Config(this);
1222
if (this.isSecure) {
1223
this.imageRoot = Module.IMG_ROOT_SSL;
1226
if (typeof el == "string") {
1228
el = document.getElementById(el);
1230
el = (createModuleTemplate()).cloneNode(false);
1241
child = this.element.firstChild;
1244
var fndHd = false, fndBd = false, fndFt = false;
1246
// We're looking for elements
1247
if (1 == child.nodeType) {
1248
if (!fndHd && Dom.hasClass(child, Module.CSS_HEADER)) {
1249
this.header = child;
1251
} else if (!fndBd && Dom.hasClass(child, Module.CSS_BODY)) {
1254
} else if (!fndFt && Dom.hasClass(child, Module.CSS_FOOTER)){
1255
this.footer = child;
1259
} while ((child = child.nextSibling));
1262
this.initDefaultConfig();
1264
Dom.addClass(this.element, Module.CSS_MODULE);
1267
this.cfg.applyConfig(userConfig, true);
1271
Subscribe to the fireQueue() method of Config so that any
1272
queued configuration changes are excecuted upon render of
1276
if (!Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) {
1277
this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
1280
this.initEvent.fire(Module);
1284
* Initialize an empty IFRAME that is placed out of the visible area
1285
* that can be used to detect text resize.
1286
* @method initResizeMonitor
1288
initResizeMonitor: function () {
1290
var isGeckoWin = (YAHOO.env.ua.gecko && this.platform == "windows");
1292
// Help prevent spinning loading icon which
1293
// started with FireFox 2.0.0.8/Win
1295
setTimeout(function(){self._initResizeMonitor();}, 0);
1297
this._initResizeMonitor();
1302
* Create and initialize the text resize monitoring iframe.
1305
* @method _initResizeMonitor
1307
_initResizeMonitor : function() {
1313
function fireTextResize() {
1314
Module.textResizeEvent.fire();
1317
if (!YAHOO.env.ua.opera) {
1318
oIFrame = Dom.get("_yuiResizeMonitor");
1320
var supportsCWResize = this._supportsCWResize();
1323
oIFrame = document.createElement("iframe");
1325
if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && YAHOO.env.ua.ie) {
1326
oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL;
1329
if (!supportsCWResize) {
1330
// Can't monitor on contentWindow, so fire from inside iframe
1331
sHTML = ["<html><head><script ",
1332
"type=\"text/javascript\">",
1333
"window.onresize=function(){window.parent.",
1334
"YAHOO.widget.Module.textResizeEvent.",
1337
"<body></body></html>"].join('');
1339
oIFrame.src = "data:text/html;charset=utf-8," + encodeURIComponent(sHTML);
1342
oIFrame.id = "_yuiResizeMonitor";
1344
Need to set "position" property before inserting the
1345
iframe into the document or Safari's status bar will
1346
forever indicate the iframe is loading
1347
(See SourceForge bug #1723064)
1349
oIFrame.style.position = "absolute";
1350
oIFrame.style.visibility = "hidden";
1352
var db = document.body,
1355
db.insertBefore(oIFrame, fc);
1357
db.appendChild(oIFrame);
1360
oIFrame.style.width = "10em";
1361
oIFrame.style.height = "10em";
1362
oIFrame.style.top = (-1 * oIFrame.offsetHeight) + "px";
1363
oIFrame.style.left = (-1 * oIFrame.offsetWidth) + "px";
1364
oIFrame.style.borderWidth = "0";
1365
oIFrame.style.visibility = "visible";
1368
Don't open/close the document for Gecko like we used to, since it
1369
leads to duplicate cookies. (See SourceForge bug #1721755)
1371
if (YAHOO.env.ua.webkit) {
1372
oDoc = oIFrame.contentWindow.document;
1378
if (oIFrame && oIFrame.contentWindow) {
1379
Module.textResizeEvent.subscribe(this.onDomResize, this, true);
1381
if (!Module.textResizeInitialized) {
1382
if (supportsCWResize) {
1383
if (!Event.on(oIFrame.contentWindow, "resize", fireTextResize)) {
1385
This will fail in IE if document.domain has
1386
changed, so we must change the listener to
1387
use the oIFrame element instead
1389
Event.on(oIFrame, "resize", fireTextResize);
1392
Module.textResizeInitialized = true;
1394
this.resizeMonitor = oIFrame;
1400
* Text resize monitor helper method.
1401
* Determines if the browser supports resize events on iframe content windows.
1404
* @method _supportsCWResize
1406
_supportsCWResize : function() {
1408
Gecko 1.8.0 (FF1.5), 1.8.1.0-5 (FF2) won't fire resize on contentWindow.
1409
Gecko 1.8.1.6+ (FF2.0.0.6+) and all other browsers will fire resize on contentWindow.
1411
We don't want to start sniffing for patch versions, so fire textResize the same
1412
way on all FF, until 1.9 (3.x) is out
1414
var bSupported = true;
1415
if (YAHOO.env.ua.gecko && YAHOO.env.ua.gecko <= 1.8) {
1418
var v = navigator.userAgent.match(/rv:([^\s\)]*)/); // From YAHOO.env.ua
1420
var sv = v[0].match(/\d\.\d\.(\d)/);
1422
if (parseInt(sv[1], 10) > 0) {
1433
* Event handler fired when the resize monitor element is resized.
1434
* @method onDomResize
1435
* @param {DOMEvent} e The DOM resize event
1436
* @param {Object} obj The scope object passed to the handler
1438
onDomResize: function (e, obj) {
1440
var nLeft = -1 * this.resizeMonitor.offsetWidth,
1441
nTop = -1 * this.resizeMonitor.offsetHeight;
1443
this.resizeMonitor.style.top = nTop + "px";
1444
this.resizeMonitor.style.left = nLeft + "px";
1449
* Sets the Module's header content to the string specified, or appends
1450
* the passed element to the header. If no header is present, one will
1451
* be automatically created. An empty string can be passed to the method
1452
* to clear the contents of the header.
1455
* @param {String} headerContent The string used to set the header.
1456
* As a convenience, non HTMLElement objects can also be passed into
1457
* the method, and will be treated as strings, with the header innerHTML
1458
* set to their default toString implementations.
1460
* @param {HTMLElement} headerContent The HTMLElement to append to
1463
setHeader: function (headerContent) {
1464
var oHeader = this.header || (this.header = createHeader());
1466
if (headerContent.tagName) {
1467
oHeader.innerHTML = "";
1468
oHeader.appendChild(headerContent);
1470
oHeader.innerHTML = headerContent;
1473
this.changeHeaderEvent.fire(headerContent);
1474
this.changeContentEvent.fire();
1479
* Appends the passed element to the header. If no header is present,
1480
* one will be automatically created.
1481
* @method appendToHeader
1482
* @param {HTMLElement} element The element to append to the header
1484
appendToHeader: function (element) {
1485
var oHeader = this.header || (this.header = createHeader());
1487
oHeader.appendChild(element);
1489
this.changeHeaderEvent.fire(element);
1490
this.changeContentEvent.fire();
1495
* Sets the Module's body content to the HTML specified, or appends the
1496
* passed element to the body. If no body is present, one will be
1497
* automatically created. An empty string can be passed to the method
1498
* to clear the contents of the body.
1500
* @param {String} bodyContent The HTML used to set the body.
1501
* As a convenience, non HTMLElement objects can also be passed into
1502
* the method, and will be treated as strings, with the body innerHTML
1503
* set to their default toString implementations.
1505
* @param {HTMLElement} bodyContent The HTMLElement to append to the body
1507
setBody: function (bodyContent) {
1508
var oBody = this.body || (this.body = createBody());
1510
if (bodyContent.tagName) {
1511
oBody.innerHTML = "";
1512
oBody.appendChild(bodyContent);
1514
oBody.innerHTML = bodyContent;
1517
this.changeBodyEvent.fire(bodyContent);
1518
this.changeContentEvent.fire();
1522
* Appends the passed element to the body. If no body is present, one
1523
* will be automatically created.
1524
* @method appendToBody
1525
* @param {HTMLElement} element The element to append to the body
1527
appendToBody: function (element) {
1528
var oBody = this.body || (this.body = createBody());
1530
oBody.appendChild(element);
1532
this.changeBodyEvent.fire(element);
1533
this.changeContentEvent.fire();
1538
* Sets the Module's footer content to the HTML specified, or appends
1539
* the passed element to the footer. If no footer is present, one will
1540
* be automatically created. An empty string can be passed to the method
1541
* to clear the contents of the footer.
1543
* @param {String} footerContent The HTML used to set the footer
1544
* As a convenience, non HTMLElement objects can also be passed into
1545
* the method, and will be treated as strings, with the footer innerHTML
1546
* set to their default toString implementations.
1548
* @param {HTMLElement} footerContent The HTMLElement to append to
1551
setFooter: function (footerContent) {
1553
var oFooter = this.footer || (this.footer = createFooter());
1555
if (footerContent.tagName) {
1556
oFooter.innerHTML = "";
1557
oFooter.appendChild(footerContent);
1559
oFooter.innerHTML = footerContent;
1562
this.changeFooterEvent.fire(footerContent);
1563
this.changeContentEvent.fire();
1568
* Appends the passed element to the footer. If no footer is present,
1569
* one will be automatically created.
1570
* @method appendToFooter
1571
* @param {HTMLElement} element The element to append to the footer
1573
appendToFooter: function (element) {
1575
var oFooter = this.footer || (this.footer = createFooter());
1577
oFooter.appendChild(element);
1579
this.changeFooterEvent.fire(element);
1580
this.changeContentEvent.fire();
1585
* Renders the Module by inserting the elements that are not already
1586
* in the main Module into their correct places. Optionally appends
1587
* the Module to the specified node prior to the render's execution.
1589
* For Modules without existing markup, the appendToNode argument
1590
* is REQUIRED. If this argument is ommitted and the current element is
1591
* not present in the document, the function will return false,
1592
* indicating that the render was a failure.
1595
* NOTE: As of 2.3.1, if the appendToNode is the document's body element
1596
* then the module is rendered as the first child of the body element,
1597
* and not appended to it, to avoid Operation Aborted errors in IE when
1598
* rendering the module before window's load event is fired. You can
1599
* use the appendtodocumentbody configuration property to change this
1600
* to append to document.body if required.
1603
* @param {String} appendToNode The element id to which the Module
1604
* should be appended to prior to rendering <em>OR</em>
1605
* @param {HTMLElement} appendToNode The element to which the Module
1606
* should be appended to prior to rendering
1607
* @param {HTMLElement} moduleElement OPTIONAL. The element that
1608
* represents the actual Standard Module container.
1609
* @return {Boolean} Success or failure of the render
1611
render: function (appendToNode, moduleElement) {
1616
function appendTo(parentNode) {
1617
if (typeof parentNode == "string") {
1618
parentNode = document.getElementById(parentNode);
1622
me._addToParent(parentNode, me.element);
1623
me.appendEvent.fire();
1627
this.beforeRenderEvent.fire();
1629
if (! moduleElement) {
1630
moduleElement = this.element;
1634
appendTo(appendToNode);
1636
// No node was passed in. If the element is not already in the Dom, this fails
1637
if (! Dom.inDocument(this.element)) {
1642
// Need to get everything into the DOM if it isn't already
1643
if (this.header && ! Dom.inDocument(this.header)) {
1644
// There is a header, but it's not in the DOM yet. Need to add it.
1645
firstChild = moduleElement.firstChild;
1647
moduleElement.insertBefore(this.header, firstChild);
1649
moduleElement.appendChild(this.header);
1653
if (this.body && ! Dom.inDocument(this.body)) {
1654
// There is a body, but it's not in the DOM yet. Need to add it.
1655
if (this.footer && Dom.isAncestor(this.moduleElement, this.footer)) {
1656
moduleElement.insertBefore(this.body, this.footer);
1658
moduleElement.appendChild(this.body);
1662
if (this.footer && ! Dom.inDocument(this.footer)) {
1663
// There is a footer, but it's not in the DOM yet. Need to add it.
1664
moduleElement.appendChild(this.footer);
1667
this.renderEvent.fire();
1672
* Removes the Module element from the DOM and sets all child elements
1676
destroy: function () {
1682
Event.purgeElement(this.element, true);
1683
parent = this.element.parentNode;
1687
parent.removeChild(this.element);
1690
this.element = null;
1695
Module.textResizeEvent.unsubscribe(this.onDomResize, this);
1700
this.destroyEvent.fire();
1703
if (e instanceof CustomEvent) {
1711
* Shows the Module element by setting the visible configuration
1712
* property to true. Also fires two events: beforeShowEvent prior to
1713
* the visibility change, and showEvent after.
1717
this.cfg.setProperty("visible", true);
1721
* Hides the Module element by setting the visible configuration
1722
* property to false. Also fires two events: beforeHideEvent prior to
1723
* the visibility change, and hideEvent after.
1727
this.cfg.setProperty("visible", false);
1730
// BUILT-IN EVENT HANDLERS FOR MODULE //
1732
* Default event handler for changing the visibility property of a
1733
* Module. By default, this is achieved by switching the "display" style
1734
* between "block" and "none".
1735
* This method is responsible for firing showEvent and hideEvent.
1736
* @param {String} type The CustomEvent type (usually the property name)
1737
* @param {Object[]} args The CustomEvent arguments. For configuration
1738
* handlers, args[0] will equal the newly applied value for the property.
1739
* @param {Object} obj The scope object. For configuration handlers,
1740
* this will usually equal the owner.
1741
* @method configVisible
1743
configVisible: function (type, args, obj) {
1744
var visible = args[0];
1746
this.beforeShowEvent.fire();
1747
Dom.setStyle(this.element, "display", "block");
1748
this.showEvent.fire();
1750
this.beforeHideEvent.fire();
1751
Dom.setStyle(this.element, "display", "none");
1752
this.hideEvent.fire();
1757
* Default event handler for the "monitorresize" configuration property
1758
* @param {String} type The CustomEvent type (usually the property name)
1759
* @param {Object[]} args The CustomEvent arguments. For configuration
1760
* handlers, args[0] will equal the newly applied value for the property.
1761
* @param {Object} obj The scope object. For configuration handlers,
1762
* this will usually equal the owner.
1763
* @method configMonitorResize
1765
configMonitorResize: function (type, args, obj) {
1766
var monitor = args[0];
1768
this.initResizeMonitor();
1770
Module.textResizeEvent.unsubscribe(this.onDomResize, this, true);
1771
this.resizeMonitor = null;
1776
* This method is a protected helper, used when constructing the DOM structure for the module
1777
* to account for situations which may cause Operation Aborted errors in IE. It should not
1778
* be used for general DOM construction.
1780
* If the parentNode is not document.body, the element is appended as the last element.
1783
* If the parentNode is document.body the element is added as the first child to help
1784
* prevent Operation Aborted errors in IE.
1787
* @param {parentNode} The HTML element to which the element will be added
1788
* @param {element} The HTML element to be added to parentNode's children
1789
* @method _addToParent
1792
_addToParent: function(parentNode, element) {
1793
if (!this.cfg.getProperty("appendtodocumentbody") && parentNode === document.body && parentNode.firstChild) {
1794
parentNode.insertBefore(element, parentNode.firstChild);
1796
parentNode.appendChild(element);
1801
* Returns a String representation of the Object.
1803
* @return {String} The string representation of the Module
1805
toString: function () {
1806
return "Module " + this.id;
1810
YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
1817
* Overlay is a Module that is absolutely positioned above the page flow. It
1818
* has convenience methods for positioning and sizing, as well as options for
1819
* controlling zIndex and constraining the Overlay's position to the current
1820
* visible viewport. Overlay also contains a dynamicly generated IFRAME which
1821
* is placed beneath it for Internet Explorer 6 and 5.x so that it will be
1822
* properly rendered above SELECT elements.
1823
* @namespace YAHOO.widget
1825
* @extends YAHOO.widget.Module
1826
* @param {String} el The element ID representing the Overlay <em>OR</em>
1827
* @param {HTMLElement} el The element representing the Overlay
1828
* @param {Object} userConfig The configuration object literal containing
1829
* the configuration that should be set for this Overlay. See configuration
1830
* documentation for more details.
1833
YAHOO.widget.Overlay = function (el, userConfig) {
1834
YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
1837
var Lang = YAHOO.lang,
1838
CustomEvent = YAHOO.util.CustomEvent,
1839
Module = YAHOO.widget.Module,
1840
Event = YAHOO.util.Event,
1841
Dom = YAHOO.util.Dom,
1842
Config = YAHOO.util.Config,
1843
Overlay = YAHOO.widget.Overlay,
1848
* Constant representing the name of the Overlay's events
1849
* @property EVENT_TYPES
1855
"BEFORE_MOVE": "beforeMove",
1860
* Constant representing the Overlay's configuration properties
1861
* @property DEFAULT_CONFIG
1870
validator: Lang.isNumber,
1871
suppressEvent: true,
1872
supercedes: ["iframe"]
1877
validator: Lang.isNumber,
1878
suppressEvent: true,
1879
supercedes: ["iframe"]
1884
suppressEvent: true,
1885
supercedes: ["iframe"]
1890
suppressEvent: true,
1891
supercedes: ["iframe"]
1897
validator: Lang.isBoolean,
1898
supercedes: ["iframe", "visible"]
1903
suppressEvent: true,
1904
supercedes: ["context", "fixedcenter", "iframe"]
1909
suppressEvent: true,
1910
supercedes: ["context", "fixedcenter", "iframe"]
1918
"CONSTRAIN_TO_VIEWPORT": {
1919
key: "constraintoviewport",
1921
validator: Lang.isBoolean,
1922
supercedes: ["iframe", "x", "y", "xy"]
1927
value: (YAHOO.env.ua.ie == 6 ? true : false),
1928
validator: Lang.isBoolean,
1929
supercedes: ["zindex"]
1934
* The URL that will be placed in the iframe
1935
* @property YAHOO.widget.Overlay.IFRAME_SRC
1940
Overlay.IFRAME_SRC = "javascript:false;";
1943
* Number representing how much the iframe shim should be offset from each
1944
* side of an Overlay instance, in pixels.
1945
* @property YAHOO.widget.Overlay.IFRAME_SRC
1951
Overlay.IFRAME_OFFSET = 3;
1954
* Number representing the minimum distance an Overlay instance should be
1955
* positioned relative to the boundaries of the browser's viewport, in pixels.
1956
* @property YAHOO.widget.Overlay.VIEWPORT_OFFSET
1962
Overlay.VIEWPORT_OFFSET = 10;
1965
* Constant representing the top left corner of an element, used for
1966
* configuring the context element alignment
1967
* @property YAHOO.widget.Overlay.TOP_LEFT
1972
Overlay.TOP_LEFT = "tl";
1975
* Constant representing the top right corner of an element, used for
1976
* configuring the context element alignment
1977
* @property YAHOO.widget.Overlay.TOP_RIGHT
1982
Overlay.TOP_RIGHT = "tr";
1985
* Constant representing the top bottom left corner of an element, used for
1986
* configuring the context element alignment
1987
* @property YAHOO.widget.Overlay.BOTTOM_LEFT
1992
Overlay.BOTTOM_LEFT = "bl";
1995
* Constant representing the bottom right corner of an element, used for
1996
* configuring the context element alignment
1997
* @property YAHOO.widget.Overlay.BOTTOM_RIGHT
2002
Overlay.BOTTOM_RIGHT = "br";
2005
* Constant representing the default CSS class used for an Overlay
2006
* @property YAHOO.widget.Overlay.CSS_OVERLAY
2011
Overlay.CSS_OVERLAY = "yui-overlay";
2014
* A singleton CustomEvent used for reacting to the DOM event for
2016
* @event YAHOO.widget.Overlay.windowScrollEvent
2018
Overlay.windowScrollEvent = new CustomEvent("windowScroll");
2021
* A singleton CustomEvent used for reacting to the DOM event for
2023
* @event YAHOO.widget.Overlay.windowResizeEvent
2025
Overlay.windowResizeEvent = new CustomEvent("windowResize");
2028
* The DOM event handler used to fire the CustomEvent for window scroll
2029
* @method YAHOO.widget.Overlay.windowScrollHandler
2031
* @param {DOMEvent} e The DOM scroll event
2033
Overlay.windowScrollHandler = function (e) {
2035
if (YAHOO.env.ua.ie) {
2037
if (! window.scrollEnd) {
2038
window.scrollEnd = -1;
2041
clearTimeout(window.scrollEnd);
2043
window.scrollEnd = setTimeout(function () {
2044
Overlay.windowScrollEvent.fire();
2048
Overlay.windowScrollEvent.fire();
2053
* The DOM event handler used to fire the CustomEvent for window resize
2054
* @method YAHOO.widget.Overlay.windowResizeHandler
2056
* @param {DOMEvent} e The DOM resize event
2058
Overlay.windowResizeHandler = function (e) {
2060
if (YAHOO.env.ua.ie) {
2061
if (! window.resizeEnd) {
2062
window.resizeEnd = -1;
2065
clearTimeout(window.resizeEnd);
2067
window.resizeEnd = setTimeout(function () {
2068
Overlay.windowResizeEvent.fire();
2071
Overlay.windowResizeEvent.fire();
2076
* A boolean that indicated whether the window resize and scroll events have
2077
* already been subscribed to.
2078
* @property YAHOO.widget.Overlay._initialized
2082
Overlay._initialized = null;
2084
if (Overlay._initialized === null) {
2085
Event.on(window, "scroll", Overlay.windowScrollHandler);
2086
Event.on(window, "resize", Overlay.windowResizeHandler);
2088
Overlay._initialized = true;
2091
YAHOO.extend(Overlay, Module, {
2094
* The Overlay initialization method, which is executed for Overlay and
2095
* all of its subclasses. This method is automatically called by the
2096
* constructor, and sets up all DOM references for pre-existing markup,
2097
* and creates required markup if it is not already present.
2099
* @param {String} el The element ID representing the Overlay <em>OR</em>
2100
* @param {HTMLElement} el The element representing the Overlay
2101
* @param {Object} userConfig The configuration object literal
2102
* containing the configuration that should be set for this Overlay.
2103
* See configuration documentation for more details.
2105
init: function (el, userConfig) {
2108
Note that we don't pass the user config in here yet because we
2109
only want it executed once, at the lowest subclass level
2112
Overlay.superclass.init.call(this, el/*, userConfig*/);
2114
this.beforeInitEvent.fire(Overlay);
2116
Dom.addClass(this.element, Overlay.CSS_OVERLAY);
2119
this.cfg.applyConfig(userConfig, true);
2122
if (this.platform == "mac" && YAHOO.env.ua.gecko) {
2124
if (! Config.alreadySubscribed(this.showEvent,
2125
this.showMacGeckoScrollbars, this)) {
2127
this.showEvent.subscribe(this.showMacGeckoScrollbars,
2132
if (! Config.alreadySubscribed(this.hideEvent,
2133
this.hideMacGeckoScrollbars, this)) {
2135
this.hideEvent.subscribe(this.hideMacGeckoScrollbars,
2141
this.initEvent.fire(Overlay);
2145
* Initializes the custom events for Overlay which are fired
2146
* automatically at appropriate times by the Overlay class.
2147
* @method initEvents
2149
initEvents: function () {
2151
Overlay.superclass.initEvents.call(this);
2153
var SIGNATURE = CustomEvent.LIST;
2156
* CustomEvent fired before the Overlay is moved.
2157
* @event beforeMoveEvent
2158
* @param {Number} x x coordinate
2159
* @param {Number} y y coordinate
2161
this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
2162
this.beforeMoveEvent.signature = SIGNATURE;
2165
* CustomEvent fired after the Overlay is moved.
2167
* @param {Number} x x coordinate
2168
* @param {Number} y y coordinate
2170
this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
2171
this.moveEvent.signature = SIGNATURE;
2176
* Initializes the class's configurable properties which can be changed
2177
* using the Overlay's Config object (cfg).
2178
* @method initDefaultConfig
2180
initDefaultConfig: function () {
2182
Overlay.superclass.initDefaultConfig.call(this);
2185
// Add overlay config properties //
2188
* The absolute x-coordinate position of the Overlay
2193
this.cfg.addProperty(DEFAULT_CONFIG.X.key, {
2195
handler: this.configX,
2196
validator: DEFAULT_CONFIG.X.validator,
2197
suppressEvent: DEFAULT_CONFIG.X.suppressEvent,
2198
supercedes: DEFAULT_CONFIG.X.supercedes
2203
* The absolute y-coordinate position of the Overlay
2208
this.cfg.addProperty(DEFAULT_CONFIG.Y.key, {
2210
handler: this.configY,
2211
validator: DEFAULT_CONFIG.Y.validator,
2212
suppressEvent: DEFAULT_CONFIG.Y.suppressEvent,
2213
supercedes: DEFAULT_CONFIG.Y.supercedes
2218
* An array with the absolute x and y positions of the Overlay
2223
this.cfg.addProperty(DEFAULT_CONFIG.XY.key, {
2225
handler: this.configXY,
2226
suppressEvent: DEFAULT_CONFIG.XY.suppressEvent,
2227
supercedes: DEFAULT_CONFIG.XY.supercedes
2232
* The array of context arguments for context-sensitive positioning.
2233
* The format is: [id or element, element corner, context corner].
2234
* For example, setting this property to ["img1", "tl", "bl"] would
2235
* align the Overlay's top left corner to the context element's
2236
* bottom left corner.
2241
this.cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
2243
handler: this.configContext,
2244
suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent,
2245
supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
2250
* True if the Overlay should be anchored to the center of
2252
* @config fixedcenter
2256
this.cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
2258
handler: this.configFixedCenter,
2259
value: DEFAULT_CONFIG.FIXED_CENTER.value,
2260
validator: DEFAULT_CONFIG.FIXED_CENTER.validator,
2261
supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
2266
* CSS width of the Overlay.
2271
this.cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
2273
handler: this.configWidth,
2274
suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent,
2275
supercedes: DEFAULT_CONFIG.WIDTH.supercedes
2280
* CSS height of the Overlay.
2285
this.cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
2287
handler: this.configHeight,
2288
suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent,
2289
supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
2294
* CSS z-index of the Overlay.
2299
this.cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
2301
handler: this.configzIndex,
2302
value: DEFAULT_CONFIG.ZINDEX.value
2307
* True if the Overlay should be prevented from being positioned
2308
* out of the viewport.
2309
* @config constraintoviewport
2313
this.cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
2315
handler: this.configConstrainToViewport,
2316
value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value,
2317
validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator,
2318
supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
2324
* @description Boolean indicating whether or not the Overlay should
2325
* have an IFRAME shim; used to prevent SELECT elements from
2326
* poking through an Overlay instance in IE6. When set to "true",
2327
* the iframe shim is created when the Overlay instance is intially
2330
* @default true for IE6 and below, false for all other browsers.
2332
this.cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
2334
handler: this.configIframe,
2335
value: DEFAULT_CONFIG.IFRAME.value,
2336
validator: DEFAULT_CONFIG.IFRAME.validator,
2337
supercedes: DEFAULT_CONFIG.IFRAME.supercedes
2343
* Moves the Overlay to the specified position. This function is
2344
* identical to calling this.cfg.setProperty("xy", [x,y]);
2346
* @param {Number} x The Overlay's new x position
2347
* @param {Number} y The Overlay's new y position
2349
moveTo: function (x, y) {
2350
this.cfg.setProperty("xy", [x, y]);
2354
* Adds a CSS class ("hide-scrollbars") and removes a CSS class
2355
* ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X
2356
* (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2357
* @method hideMacGeckoScrollbars
2359
hideMacGeckoScrollbars: function () {
2361
Dom.removeClass(this.element, "show-scrollbars");
2362
Dom.addClass(this.element, "hide-scrollbars");
2367
* Adds a CSS class ("show-scrollbars") and removes a CSS class
2368
* ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X
2369
* (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2370
* @method showMacGeckoScrollbars
2372
showMacGeckoScrollbars: function () {
2374
Dom.removeClass(this.element, "hide-scrollbars");
2375
Dom.addClass(this.element, "show-scrollbars");
2379
// BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
2381
* The default event handler fired when the "visible" property is
2382
* changed. This method is responsible for firing showEvent
2384
* @method configVisible
2385
* @param {String} type The CustomEvent type (usually the property name)
2386
* @param {Object[]} args The CustomEvent arguments. For configuration
2387
* handlers, args[0] will equal the newly applied value for the property.
2388
* @param {Object} obj The scope object. For configuration handlers,
2389
* this will usually equal the owner.
2391
configVisible: function (type, args, obj) {
2393
var visible = args[0],
2394
currentVis = Dom.getStyle(this.element, "visibility"),
2395
effect = this.cfg.getProperty("effect"),
2396
effectInstances = [],
2397
isMacGecko = (this.platform == "mac" && YAHOO.env.ua.gecko),
2398
alreadySubscribed = Config.alreadySubscribed,
2399
eff, ei, e, i, j, k, h,
2403
if (currentVis == "inherit") {
2404
e = this.element.parentNode;
2406
while (e.nodeType != 9 && e.nodeType != 11) {
2407
currentVis = Dom.getStyle(e, "visibility");
2409
if (currentVis != "inherit") {
2416
if (currentVis == "inherit") {
2417
currentVis = "visible";
2422
if (effect instanceof Array) {
2423
nEffects = effect.length;
2425
for (i = 0; i < nEffects; i++) {
2427
effectInstances[effectInstances.length] =
2428
eff.effect(this, eff.duration);
2432
effectInstances[effectInstances.length] =
2433
effect.effect(this, effect.duration);
2438
if (visible) { // Show
2440
this.showMacGeckoScrollbars();
2443
if (effect) { // Animate in
2444
if (visible) { // Animate in if not showing
2445
if (currentVis != "visible" || currentVis === "") {
2446
this.beforeShowEvent.fire();
2447
nEffectInstances = effectInstances.length;
2449
for (j = 0; j < nEffectInstances; j++) {
2450
ei = effectInstances[j];
2451
if (j === 0 && !alreadySubscribed(
2452
ei.animateInCompleteEvent,
2453
this.showEvent.fire, this.showEvent)) {
2456
Delegate showEvent until end
2457
of animateInComplete
2460
ei.animateInCompleteEvent.subscribe(
2461
this.showEvent.fire, this.showEvent, true);
2468
if (currentVis != "visible" || currentVis === "") {
2469
this.beforeShowEvent.fire();
2471
Dom.setStyle(this.element, "visibility", "visible");
2473
this.cfg.refireEvent("iframe");
2474
this.showEvent.fire();
2480
this.hideMacGeckoScrollbars();
2483
if (effect) { // Animate out if showing
2484
if (currentVis == "visible") {
2485
this.beforeHideEvent.fire();
2487
nEffectInstances = effectInstances.length;
2488
for (k = 0; k < nEffectInstances; k++) {
2489
h = effectInstances[k];
2491
if (k === 0 && !alreadySubscribed(
2492
h.animateOutCompleteEvent, this.hideEvent.fire,
2496
Delegate hideEvent until end
2497
of animateOutComplete
2500
h.animateOutCompleteEvent.subscribe(
2501
this.hideEvent.fire, this.hideEvent, true);
2507
} else if (currentVis === "") {
2508
Dom.setStyle(this.element, "visibility", "hidden");
2511
} else { // Simple hide
2513
if (currentVis == "visible" || currentVis === "") {
2514
this.beforeHideEvent.fire();
2515
Dom.setStyle(this.element, "visibility", "hidden");
2516
this.hideEvent.fire();
2523
* Center event handler used for centering on scroll/resize, but only if
2524
* the Overlay is visible
2525
* @method doCenterOnDOMEvent
2527
doCenterOnDOMEvent: function () {
2528
if (this.cfg.getProperty("visible")) {
2534
* The default event handler fired when the "fixedcenter" property
2536
* @method configFixedCenter
2537
* @param {String} type The CustomEvent type (usually the property name)
2538
* @param {Object[]} args The CustomEvent arguments. For configuration
2539
* handlers, args[0] will equal the newly applied value for the property.
2540
* @param {Object} obj The scope object. For configuration handlers,
2541
* this will usually equal the owner.
2543
configFixedCenter: function (type, args, obj) {
2546
alreadySubscribed = Config.alreadySubscribed,
2547
windowResizeEvent = Overlay.windowResizeEvent,
2548
windowScrollEvent = Overlay.windowScrollEvent;
2553
if (!alreadySubscribed(this.beforeShowEvent, this.center, this)) {
2554
this.beforeShowEvent.subscribe(this.center);
2557
if (!alreadySubscribed(windowResizeEvent, this.doCenterOnDOMEvent, this)) {
2558
windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2561
if (!alreadySubscribed(windowScrollEvent, this.doCenterOnDOMEvent, this)) {
2562
windowScrollEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2566
this.beforeShowEvent.unsubscribe(this.center);
2568
windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2569
windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2574
* The default event handler fired when the "height" property is changed.
2575
* @method configHeight
2576
* @param {String} type The CustomEvent type (usually the property name)
2577
* @param {Object[]} args The CustomEvent arguments. For configuration
2578
* handlers, args[0] will equal the newly applied value for the property.
2579
* @param {Object} obj The scope object. For configuration handlers,
2580
* this will usually equal the owner.
2582
configHeight: function (type, args, obj) {
2584
var height = args[0],
2587
Dom.setStyle(el, "height", height);
2588
this.cfg.refireEvent("iframe");
2592
* The default event handler fired when the "width" property is changed.
2593
* @method configWidth
2594
* @param {String} type The CustomEvent type (usually the property name)
2595
* @param {Object[]} args The CustomEvent arguments. For configuration
2596
* handlers, args[0] will equal the newly applied value for the property.
2597
* @param {Object} obj The scope object. For configuration handlers,
2598
* this will usually equal the owner.
2600
configWidth: function (type, args, obj) {
2602
var width = args[0],
2605
Dom.setStyle(el, "width", width);
2606
this.cfg.refireEvent("iframe");
2610
* The default event handler fired when the "zIndex" property is changed.
2611
* @method configzIndex
2612
* @param {String} type The CustomEvent type (usually the property name)
2613
* @param {Object[]} args The CustomEvent arguments. For configuration
2614
* handlers, args[0] will equal the newly applied value for the property.
2615
* @param {Object} obj The scope object. For configuration handlers,
2616
* this will usually equal the owner.
2618
configzIndex: function (type, args, obj) {
2620
var zIndex = args[0],
2624
zIndex = Dom.getStyle(el, "zIndex");
2625
if (! zIndex || isNaN(zIndex)) {
2630
if (this.iframe || this.cfg.getProperty("iframe") === true) {
2636
Dom.setStyle(el, "zIndex", zIndex);
2637
this.cfg.setProperty("zIndex", zIndex, true);
2645
* The default event handler fired when the "xy" property is changed.
2647
* @param {String} type The CustomEvent type (usually the property name)
2648
* @param {Object[]} args The CustomEvent arguments. For configuration
2649
* handlers, args[0] will equal the newly applied value for the property.
2650
* @param {Object} obj The scope object. For configuration handlers,
2651
* this will usually equal the owner.
2653
configXY: function (type, args, obj) {
2659
this.cfg.setProperty("x", x);
2660
this.cfg.setProperty("y", y);
2662
this.beforeMoveEvent.fire([x, y]);
2664
x = this.cfg.getProperty("x");
2665
y = this.cfg.getProperty("y");
2668
this.cfg.refireEvent("iframe");
2669
this.moveEvent.fire([x, y]);
2673
* The default event handler fired when the "x" property is changed.
2675
* @param {String} type The CustomEvent type (usually the property name)
2676
* @param {Object[]} args The CustomEvent arguments. For configuration
2677
* handlers, args[0] will equal the newly applied value for the property.
2678
* @param {Object} obj The scope object. For configuration handlers,
2679
* this will usually equal the owner.
2681
configX: function (type, args, obj) {
2684
y = this.cfg.getProperty("y");
2686
this.cfg.setProperty("x", x, true);
2687
this.cfg.setProperty("y", y, true);
2689
this.beforeMoveEvent.fire([x, y]);
2691
x = this.cfg.getProperty("x");
2692
y = this.cfg.getProperty("y");
2694
Dom.setX(this.element, x, true);
2696
this.cfg.setProperty("xy", [x, y], true);
2698
this.cfg.refireEvent("iframe");
2699
this.moveEvent.fire([x, y]);
2703
* The default event handler fired when the "y" property is changed.
2705
* @param {String} type The CustomEvent type (usually the property name)
2706
* @param {Object[]} args The CustomEvent arguments. For configuration
2707
* handlers, args[0] will equal the newly applied value for the property.
2708
* @param {Object} obj The scope object. For configuration handlers,
2709
* this will usually equal the owner.
2711
configY: function (type, args, obj) {
2713
var x = this.cfg.getProperty("x"),
2716
this.cfg.setProperty("x", x, true);
2717
this.cfg.setProperty("y", y, true);
2719
this.beforeMoveEvent.fire([x, y]);
2721
x = this.cfg.getProperty("x");
2722
y = this.cfg.getProperty("y");
2724
Dom.setY(this.element, y, true);
2726
this.cfg.setProperty("xy", [x, y], true);
2728
this.cfg.refireEvent("iframe");
2729
this.moveEvent.fire([x, y]);
2733
* Shows the iframe shim, if it has been enabled.
2734
* @method showIframe
2736
showIframe: function () {
2738
var oIFrame = this.iframe,
2742
oParentNode = this.element.parentNode;
2744
if (oParentNode != oIFrame.parentNode) {
2745
this._addToParent(oParentNode, oIFrame);
2747
oIFrame.style.display = "block";
2752
* Hides the iframe shim, if it has been enabled.
2753
* @method hideIframe
2755
hideIframe: function () {
2757
this.iframe.style.display = "none";
2762
* Syncronizes the size and position of iframe shim to that of its
2763
* corresponding Overlay instance.
2764
* @method syncIframe
2766
syncIframe: function () {
2768
var oIFrame = this.iframe,
2769
oElement = this.element,
2770
nOffset = Overlay.IFRAME_OFFSET,
2771
nDimensionOffset = (nOffset * 2),
2776
oIFrame.style.width = (oElement.offsetWidth + nDimensionOffset + "px");
2777
oIFrame.style.height = (oElement.offsetHeight + nDimensionOffset + "px");
2779
// Position <iframe>
2780
aXY = this.cfg.getProperty("xy");
2782
if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
2783
this.syncPosition();
2784
aXY = this.cfg.getProperty("xy");
2786
Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
2791
* Sets the zindex of the iframe shim, if it exists, based on the zindex of
2792
* the Overlay element. The zindex of the iframe is set to be one less
2793
* than the Overlay element's zindex.
2795
* <p>NOTE: This method will not bump up the zindex of the Overlay element
2796
* to ensure that the iframe shim has a non-negative zindex.
2797
* If you require the iframe zindex to be 0 or higher, the zindex of
2798
* the Overlay element should be set to a value greater than 0, before
2799
* this method is called.
2801
* @method stackIframe
2803
stackIframe: function () {
2805
var overlayZ = Dom.getStyle(this.element, "zIndex");
2806
if (!YAHOO.lang.isUndefined(overlayZ) && !isNaN(overlayZ)) {
2807
Dom.setStyle(this.iframe, "zIndex", (overlayZ - 1));
2813
* The default event handler fired when the "iframe" property is changed.
2814
* @method configIframe
2815
* @param {String} type The CustomEvent type (usually the property name)
2816
* @param {Object[]} args The CustomEvent arguments. For configuration
2817
* handlers, args[0] will equal the newly applied value for the property.
2818
* @param {Object} obj The scope object. For configuration handlers,
2819
* this will usually equal the owner.
2821
configIframe: function (type, args, obj) {
2823
var bIFrame = args[0];
2825
function createIFrame() {
2827
var oIFrame = this.iframe,
2828
oElement = this.element,
2832
if (!m_oIFrameTemplate) {
2833
m_oIFrameTemplate = document.createElement("iframe");
2835
if (this.isSecure) {
2836
m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
2840
Set the opacity of the <iframe> to 0 so that it
2841
doesn't modify the opacity of any transparent
2842
elements that may be on top of it (like a shadow).
2845
if (YAHOO.env.ua.ie) {
2846
m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
2848
Need to set the "frameBorder" property to 0
2849
supress the default <iframe> border in IE.
2850
Setting the CSS "border" property alone
2853
m_oIFrameTemplate.frameBorder = 0;
2856
m_oIFrameTemplate.style.opacity = "0";
2859
m_oIFrameTemplate.style.position = "absolute";
2860
m_oIFrameTemplate.style.border = "none";
2861
m_oIFrameTemplate.style.margin = "0";
2862
m_oIFrameTemplate.style.padding = "0";
2863
m_oIFrameTemplate.style.display = "none";
2866
oIFrame = m_oIFrameTemplate.cloneNode(false);
2867
oParent = oElement.parentNode;
2869
var parentNode = oParent || document.body;
2871
this._addToParent(parentNode, oIFrame);
2872
this.iframe = oIFrame;
2876
Show the <iframe> before positioning it since the "setXY"
2877
method of DOM requires the element be in the document
2883
Syncronize the size and position of the <iframe> to that
2889
// Add event listeners to update the <iframe> when necessary
2890
if (!this._hasIframeEventListeners) {
2891
this.showEvent.subscribe(this.showIframe);
2892
this.hideEvent.subscribe(this.hideIframe);
2893
this.changeContentEvent.subscribe(this.syncIframe);
2895
this._hasIframeEventListeners = true;
2899
function onBeforeShow() {
2900
createIFrame.call(this);
2901
this.beforeShowEvent.unsubscribe(onBeforeShow);
2902
this._iframeDeferred = false;
2905
if (bIFrame) { // <iframe> shim is enabled
2907
if (this.cfg.getProperty("visible")) {
2908
createIFrame.call(this);
2910
if (!this._iframeDeferred) {
2911
this.beforeShowEvent.subscribe(onBeforeShow);
2912
this._iframeDeferred = true;
2916
} else { // <iframe> shim is disabled
2919
if (this._hasIframeEventListeners) {
2920
this.showEvent.unsubscribe(this.showIframe);
2921
this.hideEvent.unsubscribe(this.hideIframe);
2922
this.changeContentEvent.unsubscribe(this.syncIframe);
2924
this._hasIframeEventListeners = false;
2930
* Set's the container's XY value from DOM if not already set.
2932
* Differs from syncPosition, in that the XY value is only sync'd with DOM if
2933
* not already set. The method also refire's the XY config property event, so any
2934
* beforeMove, Move event listeners are invoked.
2936
* @method _primeXYFromDOM
2939
_primeXYFromDOM : function() {
2940
if (YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))) {
2941
// Set CFG XY based on DOM XY
2942
this.syncPosition();
2943
// Account for XY being set silently in syncPosition (no moveTo fired/called)
2944
this.cfg.refireEvent("xy");
2945
this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
2950
* The default event handler fired when the "constraintoviewport"
2951
* property is changed.
2952
* @method configConstrainToViewport
2953
* @param {String} type The CustomEvent type (usually the property name)
2954
* @param {Object[]} args The CustomEvent arguments. For configuration
2955
* handlers, args[0] will equal the newly applied value for
2957
* @param {Object} obj The scope object. For configuration handlers,
2958
* this will usually equal the owner.
2960
configConstrainToViewport: function (type, args, obj) {
2964
if (! Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
2965
this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
2967
if (! Config.alreadySubscribed(this.beforeShowEvent, this._primeXYFromDOM)) {
2968
this.beforeShowEvent.subscribe(this._primeXYFromDOM);
2971
this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
2972
this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
2977
* The default event handler fired when the "context" property
2979
* @method configContext
2980
* @param {String} type The CustomEvent type (usually the property name)
2981
* @param {Object[]} args The CustomEvent arguments. For configuration
2982
* handlers, args[0] will equal the newly applied value for the property.
2983
* @param {Object} obj The scope object. For configuration handlers,
2984
* this will usually equal the owner.
2986
configContext: function (type, args, obj) {
2988
var contextArgs = args[0],
2990
elementMagnetCorner,
2991
contextMagnetCorner;
2994
contextEl = contextArgs[0];
2995
elementMagnetCorner = contextArgs[1];
2996
contextMagnetCorner = contextArgs[2];
2999
if (typeof contextEl == "string") {
3000
this.cfg.setProperty("context",
3001
[document.getElementById(contextEl),
3002
elementMagnetCorner, contextMagnetCorner],
3006
if (elementMagnetCorner && contextMagnetCorner) {
3007
this.align(elementMagnetCorner, contextMagnetCorner);
3013
// END BUILT-IN PROPERTY EVENT HANDLERS //
3015
* Aligns the Overlay to its context element using the specified corner
3016
* points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT,
3019
* @param {String} elementAlign The String representing the corner of
3020
* the Overlay that should be aligned to the context element
3021
* @param {String} contextAlign The corner of the context element
3022
* that the elementAlign corner should stick to.
3024
align: function (elementAlign, contextAlign) {
3026
var contextArgs = this.cfg.getProperty("context"),
3032
function doAlign(v, h) {
3034
switch (elementAlign) {
3036
case Overlay.TOP_LEFT:
3040
case Overlay.TOP_RIGHT:
3041
me.moveTo((h - element.offsetWidth), v);
3044
case Overlay.BOTTOM_LEFT:
3045
me.moveTo(h, (v - element.offsetHeight));
3048
case Overlay.BOTTOM_RIGHT:
3049
me.moveTo((h - element.offsetWidth),
3050
(v - element.offsetHeight));
3058
context = contextArgs[0];
3059
element = this.element;
3062
if (! elementAlign) {
3063
elementAlign = contextArgs[1];
3066
if (! contextAlign) {
3067
contextAlign = contextArgs[2];
3070
if (element && context) {
3071
contextRegion = Dom.getRegion(context);
3073
switch (contextAlign) {
3075
case Overlay.TOP_LEFT:
3076
doAlign(contextRegion.top, contextRegion.left);
3079
case Overlay.TOP_RIGHT:
3080
doAlign(contextRegion.top, contextRegion.right);
3083
case Overlay.BOTTOM_LEFT:
3084
doAlign(contextRegion.bottom, contextRegion.left);
3087
case Overlay.BOTTOM_RIGHT:
3088
doAlign(contextRegion.bottom, contextRegion.right);
3099
* The default event handler executed when the moveEvent is fired, if the
3100
* "constraintoviewport" is set to true.
3101
* @method enforceConstraints
3102
* @param {String} type The CustomEvent type (usually the property name)
3103
* @param {Object[]} args The CustomEvent arguments. For configuration
3104
* handlers, args[0] will equal the newly applied value for the property.
3105
* @param {Object} obj The scope object. For configuration handlers,
3106
* this will usually equal the owner.
3108
enforceConstraints: function (type, args, obj) {
3110
var cXY = this.getConstrainedXY(pos[0], pos[1]);
3111
this.cfg.setProperty("x", cXY[0], true);
3112
this.cfg.setProperty("y", cXY[1], true);
3113
this.cfg.setProperty("xy", cXY, true);
3117
* Given x, y coordinate values, returns the calculated coordinates required to
3118
* position the Overlay if it is to be constrained to the viewport, based on the
3119
* current element size, viewport dimensions and scroll values.
3121
* @param {Number} x The X coordinate value to be constrained
3122
* @param {Number} y The Y coordinate value to be constrained
3123
* @return {Array} The constrained x and y coordinates at index 0 and 1 respectively;
3125
getConstrainedXY: function(x, y) {
3127
var nViewportOffset = Overlay.VIEWPORT_OFFSET,
3128
viewPortWidth = Dom.getViewportWidth(),
3129
viewPortHeight = Dom.getViewportHeight(),
3130
offsetHeight = this.element.offsetHeight,
3131
offsetWidth = this.element.offsetWidth,
3132
scrollX = Dom.getDocumentScrollLeft(),
3133
scrollY = Dom.getDocumentScrollTop();
3138
if (offsetWidth + nViewportOffset < viewPortWidth) {
3140
var leftConstraint = scrollX + nViewportOffset;
3141
var rightConstraint = scrollX + viewPortWidth - offsetWidth - nViewportOffset;
3143
if (x < leftConstraint) {
3144
xNew = leftConstraint;
3145
} else if (x > rightConstraint) {
3146
xNew = rightConstraint;
3149
xNew = nViewportOffset + scrollX;
3152
if (offsetHeight + nViewportOffset < viewPortHeight) {
3154
var topConstraint = scrollY + nViewportOffset;
3155
var bottomConstraint = scrollY + viewPortHeight - offsetHeight - nViewportOffset;
3157
if (y < topConstraint) {
3158
yNew = topConstraint;
3159
} else if (y > bottomConstraint) {
3160
yNew = bottomConstraint;
3163
yNew = nViewportOffset + scrollY;
3166
return [xNew, yNew];
3170
* Centers the container in the viewport.
3173
center: function () {
3175
var nViewportOffset = Overlay.VIEWPORT_OFFSET,
3176
elementWidth = this.element.offsetWidth,
3177
elementHeight = this.element.offsetHeight,
3178
viewPortWidth = Dom.getViewportWidth(),
3179
viewPortHeight = Dom.getViewportHeight(),
3183
if (elementWidth < viewPortWidth) {
3184
x = (viewPortWidth / 2) - (elementWidth / 2) + Dom.getDocumentScrollLeft();
3186
x = nViewportOffset + Dom.getDocumentScrollLeft();
3189
if (elementHeight < viewPortHeight) {
3190
y = (viewPortHeight / 2) - (elementHeight / 2) + Dom.getDocumentScrollTop();
3192
y = nViewportOffset + Dom.getDocumentScrollTop();
3195
this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
3196
this.cfg.refireEvent("iframe");
3200
* Synchronizes the Panel's "xy", "x", and "y" properties with the
3201
* Panel's position in the DOM. This is primarily used to update
3202
* position information during drag & drop.
3203
* @method syncPosition
3205
syncPosition: function () {
3207
var pos = Dom.getXY(this.element);
3209
this.cfg.setProperty("x", pos[0], true);
3210
this.cfg.setProperty("y", pos[1], true);
3211
this.cfg.setProperty("xy", pos, true);
3216
* Event handler fired when the resize monitor element is resized.
3217
* @method onDomResize
3218
* @param {DOMEvent} e The resize DOM event
3219
* @param {Object} obj The scope object
3221
onDomResize: function (e, obj) {
3225
Overlay.superclass.onDomResize.call(this, e, obj);
3227
setTimeout(function () {
3229
me.cfg.refireEvent("iframe");
3230
me.cfg.refireEvent("context");
3236
* Places the Overlay on top of all other instances of
3237
* YAHOO.widget.Overlay.
3238
* @method bringToTop
3240
bringToTop: function () {
3243
oElement = this.element;
3245
function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
3247
var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
3248
sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
3250
nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 0 : parseInt(sZIndex1, 10),
3251
nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 0 : parseInt(sZIndex2, 10);
3253
if (nZIndex1 > nZIndex2) {
3255
} else if (nZIndex1 < nZIndex2) {
3262
function isOverlayElement(p_oElement) {
3264
var oOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
3265
Panel = YAHOO.widget.Panel;
3267
if (oOverlay && !Dom.isAncestor(oElement, oOverlay)) {
3268
if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
3269
aOverlays[aOverlays.length] = p_oElement.parentNode;
3271
aOverlays[aOverlays.length] = p_oElement;
3276
Dom.getElementsBy(isOverlayElement, "DIV", document.body);
3278
aOverlays.sort(compareZIndexDesc);
3280
var oTopOverlay = aOverlays[0],
3284
nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
3286
if (!isNaN(nTopZIndex)) {
3287
var bRequiresBump = false;
3289
if (oTopOverlay != oElement) {
3290
bRequiresBump = true;
3291
} else if (aOverlays.length > 1) {
3292
var nNextZIndex = Dom.getStyle(aOverlays[1], "zIndex");
3293
// Don't rely on DOM order to stack if 2 overlays are at the same zindex.
3294
if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
3295
bRequiresBump = true;
3298
if (bRequiresBump) {
3299
this.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
3306
* Removes the Overlay element from the DOM and sets all child
3310
destroy: function () {
3313
this.iframe.parentNode.removeChild(this.iframe);
3318
Overlay.windowResizeEvent.unsubscribe(
3319
this.doCenterOnDOMEvent, this);
3321
Overlay.windowScrollEvent.unsubscribe(
3322
this.doCenterOnDOMEvent, this);
3324
Overlay.superclass.destroy.call(this);
3328
* Returns a String representation of the object.
3330
* @return {String} The string representation of the Overlay.
3332
toString: function () {
3333
return "Overlay " + this.id;
3342
* OverlayManager is used for maintaining the focus status of
3343
* multiple Overlays.
3344
* @namespace YAHOO.widget
3345
* @namespace YAHOO.widget
3346
* @class OverlayManager
3348
* @param {Array} overlays Optional. A collection of Overlays to register
3350
* @param {Object} userConfig The object literal representing the user
3351
* configuration of the OverlayManager
3353
YAHOO.widget.OverlayManager = function (userConfig) {
3354
this.init(userConfig);
3357
var Overlay = YAHOO.widget.Overlay,
3358
Event = YAHOO.util.Event,
3359
Dom = YAHOO.util.Dom,
3360
Config = YAHOO.util.Config,
3361
CustomEvent = YAHOO.util.CustomEvent,
3362
OverlayManager = YAHOO.widget.OverlayManager;
3365
* The CSS class representing a focused Overlay
3366
* @property OverlayManager.CSS_FOCUSED
3371
OverlayManager.CSS_FOCUSED = "focused";
3373
OverlayManager.prototype = {
3376
* The class's constructor function
3377
* @property contructor
3380
constructor: OverlayManager,
3383
* The array of Overlays that are currently registered
3384
* @property overlays
3385
* @type YAHOO.widget.Overlay[]
3390
* Initializes the default configuration of the OverlayManager
3391
* @method initDefaultConfig
3393
initDefaultConfig: function () {
3396
* The collection of registered Overlays in use by
3397
* the OverlayManager
3399
* @type YAHOO.widget.Overlay[]
3402
this.cfg.addProperty("overlays", { suppressEvent: true } );
3405
* The default DOM event that should be used to focus an Overlay
3406
* @config focusevent
3408
* @default "mousedown"
3410
this.cfg.addProperty("focusevent", { value: "mousedown" } );
3415
* Initializes the OverlayManager
3417
* @param {Overlay[]} overlays Optional. A collection of Overlays to
3418
* register with the manager.
3419
* @param {Object} userConfig The object literal representing the user
3420
* configuration of the OverlayManager
3422
init: function (userConfig) {
3425
* The OverlayManager's Config object used for monitoring
3426
* configuration properties.
3430
this.cfg = new Config(this);
3432
this.initDefaultConfig();
3435
this.cfg.applyConfig(userConfig, true);
3437
this.cfg.fireQueue();
3440
* The currently activated Overlay
3441
* @property activeOverlay
3443
* @type YAHOO.widget.Overlay
3445
var activeOverlay = null;
3448
* Returns the currently focused Overlay
3450
* @return {Overlay} The currently focused Overlay
3452
this.getActive = function () {
3453
return activeOverlay;
3457
* Focuses the specified Overlay
3459
* @param {Overlay} overlay The Overlay to focus
3460
* @param {String} overlay The id of the Overlay to focus
3462
this.focus = function (overlay) {
3463
var o = this.find(overlay);
3465
if (activeOverlay != o) {
3466
if (activeOverlay) {
3467
activeOverlay.blur();
3473
Dom.addClass(activeOverlay.element,
3474
OverlayManager.CSS_FOCUSED);
3476
o.focusEvent.fire();
3482
* Removes the specified Overlay from the manager
3484
* @param {Overlay} overlay The Overlay to remove
3485
* @param {String} overlay The id of the Overlay to remove
3487
this.remove = function (overlay) {
3488
var o = this.find(overlay),
3491
if (activeOverlay == o) {
3492
activeOverlay = null;
3495
var bDestroyed = (o.element === null && o.cfg === null) ? true : false;
3498
// Set it's zindex so that it's sorted to the end.
3499
originalZ = Dom.getStyle(o.element, "zIndex");
3500
o.cfg.setProperty("zIndex", -1000, true);
3503
this.overlays.sort(this.compareZIndexDesc);
3504
this.overlays = this.overlays.slice(0, (this.overlays.length - 1));
3506
o.hideEvent.unsubscribe(o.blur);
3507
o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
3510
Event.removeListener(o.element,
3511
this.cfg.getProperty("focusevent"),
3512
this._onOverlayElementFocus);
3514
o.cfg.setProperty("zIndex", originalZ, true);
3515
o.cfg.setProperty("manager", null);
3518
o.focusEvent.unsubscribeAll();
3519
o.blurEvent.unsubscribeAll();
3521
o.focusEvent = null;
3530
* Removes focus from all registered Overlays in the manager
3533
this.blurAll = function () {
3535
var nOverlays = this.overlays.length,
3538
if (nOverlays > 0) {
3542
this.overlays[i].blur();
3548
this._onOverlayBlur = function (p_sType, p_aArgs) {
3549
activeOverlay = null;
3552
var overlays = this.cfg.getProperty("overlays");
3554
if (! this.overlays) {
3559
this.register(overlays);
3560
this.overlays.sort(this.compareZIndexDesc);
3566
* @method _onOverlayElementFocus
3567
* @description Event handler for the DOM event that is used to focus
3568
* the Overlay instance as specified by the "focusevent"
3569
* configuration property.
3571
* @param {Event} p_oEvent Object representing the DOM event
3572
* object passed back by the event utility (Event).
3574
_onOverlayElementFocus: function (p_oEvent) {
3576
var oTarget = Event.getTarget(p_oEvent),
3577
oClose = this.close;
3579
if (oClose && (oTarget == oClose || Dom.isAncestor(oClose, oTarget))) {
3588
* @method _onOverlayDestroy
3589
* @description "destroy" event handler for the Overlay.
3591
* @param {String} p_sType String representing the name of the event
3593
* @param {Array} p_aArgs Array of arguments sent when the event
3595
* @param {Overlay} p_oOverlay Object representing the menu that
3598
_onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
3599
this.remove(p_oOverlay);
3603
* Registers an Overlay or an array of Overlays with the manager. Upon
3604
* registration, the Overlay receives functions for focus and blur,
3605
* along with CustomEvents for each.
3607
* @param {Overlay} overlay An Overlay to register with the manager.
3608
* @param {Overlay[]} overlay An array of Overlays to register with
3610
* @return {Boolean} True if any Overlays are registered.
3612
register: function (overlay) {
3620
if (overlay instanceof Overlay) {
3622
overlay.cfg.addProperty("manager", { value: this } );
3624
overlay.focusEvent = overlay.createEvent("focus");
3625
overlay.focusEvent.signature = CustomEvent.LIST;
3627
overlay.blurEvent = overlay.createEvent("blur");
3628
overlay.blurEvent.signature = CustomEvent.LIST;
3630
overlay.focus = function () {
3634
overlay.blur = function () {
3635
if (mgr.getActive() == this) {
3636
Dom.removeClass(this.element, OverlayManager.CSS_FOCUSED);
3637
this.blurEvent.fire();
3641
overlay.blurEvent.subscribe(mgr._onOverlayBlur);
3642
overlay.hideEvent.subscribe(overlay.blur);
3644
overlay.destroyEvent.subscribe(this._onOverlayDestroy, overlay, this);
3646
Event.on(overlay.element, this.cfg.getProperty("focusevent"),
3647
this._onOverlayElementFocus, null, overlay);
3649
zIndex = Dom.getStyle(overlay.element, "zIndex");
3651
if (!isNaN(zIndex)) {
3652
overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
3654
overlay.cfg.setProperty("zIndex", 0);
3657
this.overlays.push(overlay);
3658
this.bringToTop(overlay);
3662
} else if (overlay instanceof Array) {
3665
nOverlays = overlay.length;
3667
for (i = 0; i < nOverlays; i++) {
3668
if (this.register(overlay[i])) {
3682
* Places the specified Overlay instance on top of all other
3683
* Overlay instances.
3684
* @method bringToTop
3685
* @param {YAHOO.widget.Overlay} p_oOverlay Object representing an
3687
* @param {String} p_oOverlay String representing the id of an
3690
bringToTop: function (p_oOverlay) {
3692
var oOverlay = this.find(p_oOverlay),
3699
aOverlays = this.overlays;
3700
aOverlays.sort(this.compareZIndexDesc);
3702
oTopOverlay = aOverlays[0];
3705
nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
3707
if (!isNaN(nTopZIndex)) {
3709
var bRequiresBump = false;
3711
if (oTopOverlay !== oOverlay) {
3712
bRequiresBump = true;
3713
} else if (aOverlays.length > 1) {
3714
var nNextZIndex = Dom.getStyle(aOverlays[1].element, "zIndex");
3715
// Don't rely on DOM order to stack if 2 overlays are at the same zindex.
3716
if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
3717
bRequiresBump = true;
3721
if (bRequiresBump) {
3722
oOverlay.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
3725
aOverlays.sort(this.compareZIndexDesc);
3731
* Attempts to locate an Overlay by instance or ID.
3733
* @param {Overlay} overlay An Overlay to locate within the manager
3734
* @param {String} overlay An Overlay id to locate within the manager
3735
* @return {Overlay} The requested Overlay, if found, or null if it
3736
* cannot be located.
3738
find: function (overlay) {
3740
var aOverlays = this.overlays,
3741
nOverlays = aOverlays.length,
3744
if (nOverlays > 0) {
3747
if (overlay instanceof Overlay) {
3749
if (aOverlays[i] == overlay) {
3750
return aOverlays[i];
3755
} else if (typeof overlay == "string") {
3757
if (aOverlays[i].id == overlay) {
3758
return aOverlays[i];
3768
* Used for sorting the manager's Overlays by z-index.
3769
* @method compareZIndexDesc
3771
* @return {Number} 0, 1, or -1, depending on where the Overlay should
3772
* fall in the stacking order.
3774
compareZIndexDesc: function (o1, o2) {
3776
var zIndex1 = (o1.cfg) ? o1.cfg.getProperty("zIndex") : null, // Sort invalid (destroyed)
3777
zIndex2 = (o2.cfg) ? o2.cfg.getProperty("zIndex") : null; // objects at bottom.
3779
if (zIndex1 === null && zIndex2 === null) {
3781
} else if (zIndex1 === null){
3783
} else if (zIndex2 === null) {
3785
} else if (zIndex1 > zIndex2) {
3787
} else if (zIndex1 < zIndex2) {
3795
* Shows all Overlays in the manager.
3798
showAll: function () {
3800
var aOverlays = this.overlays,
3801
nOverlays = aOverlays.length,
3804
if (nOverlays > 0) {
3807
aOverlays[i].show();
3814
* Hides all Overlays in the manager.
3817
hideAll: function () {
3819
var aOverlays = this.overlays,
3820
nOverlays = aOverlays.length,
3823
if (nOverlays > 0) {
3826
aOverlays[i].hide();
3833
* Returns a string representation of the object.
3835
* @return {String} The string representation of the OverlayManager
3837
toString: function () {
3838
return "OverlayManager";
3847
* Tooltip is an implementation of Overlay that behaves like an OS tooltip,
3848
* displaying when the user mouses over a particular element, and
3849
* disappearing on mouse out.
3850
* @namespace YAHOO.widget
3852
* @extends YAHOO.widget.Overlay
3854
* @param {String} el The element ID representing the Tooltip <em>OR</em>
3855
* @param {HTMLElement} el The element representing the Tooltip
3856
* @param {Object} userConfig The configuration object literal containing
3857
* the configuration that should be set for this Overlay. See configuration
3858
* documentation for more details.
3860
YAHOO.widget.Tooltip = function (el, userConfig) {
3861
YAHOO.widget.Tooltip.superclass.constructor.call(this, el, userConfig);
3864
var Lang = YAHOO.lang,
3865
Event = YAHOO.util.Event,
3866
CustomEvent = YAHOO.util.CustomEvent,
3867
Dom = YAHOO.util.Dom,
3868
Tooltip = YAHOO.widget.Tooltip,
3873
* Constant representing the Tooltip's configuration properties
3874
* @property DEFAULT_CONFIG
3881
"PREVENT_OVERLAP": {
3882
key: "preventoverlap",
3884
validator: Lang.isBoolean,
3885
supercedes: ["x", "y", "xy"]
3891
validator: Lang.isNumber
3894
"AUTO_DISMISS_DELAY": {
3895
key: "autodismissdelay",
3897
validator: Lang.isNumber
3903
validator: Lang.isNumber
3923
* Constant representing the name of the Tooltip's events
3924
* @property EVENT_TYPES
3930
"CONTEXT_MOUSE_OVER": "contextMouseOver",
3931
"CONTEXT_MOUSE_OUT": "contextMouseOut",
3932
"CONTEXT_TRIGGER": "contextTrigger"
3936
* Constant representing the Tooltip CSS class
3937
* @property YAHOO.widget.Tooltip.CSS_TOOLTIP
3942
Tooltip.CSS_TOOLTIP = "yui-tt";
3945
"hide" event handler that sets a Tooltip instance's "width"
3946
configuration property back to its original value before
3947
"setWidthToOffsetWidth" was called.
3949
function restoreOriginalWidth(p_sType, p_aArgs, p_oObject) {
3951
var sOriginalWidth = p_oObject[0],
3952
sNewWidth = p_oObject[1],
3954
sCurrentWidth = oConfig.getProperty("width");
3956
if (sCurrentWidth == sNewWidth) {
3957
oConfig.setProperty("width", sOriginalWidth);
3960
this.unsubscribe("hide", this._onHide, p_oObject);
3964
"beforeShow" event handler that sets a Tooltip instance's "width"
3965
configuration property to the value of its root HTML
3966
elements's offsetWidth
3969
function setWidthToOffsetWidth(p_sType, p_aArgs) {
3971
var oBody = document.body,
3973
sOriginalWidth = oConfig.getProperty("width"),
3977
if ((!sOriginalWidth || sOriginalWidth == "auto") &&
3978
(oConfig.getProperty("container") != oBody ||
3979
oConfig.getProperty("x") >= Dom.getViewportWidth() ||
3980
oConfig.getProperty("y") >= Dom.getViewportHeight())) {
3982
oClone = this.element.cloneNode(true);
3983
oClone.style.visibility = "hidden";
3984
oClone.style.top = "0px";
3985
oClone.style.left = "0px";
3987
oBody.appendChild(oClone);
3989
sNewWidth = (oClone.offsetWidth + "px");
3991
oBody.removeChild(oClone);
3994
oConfig.setProperty("width", sNewWidth);
3995
oConfig.refireEvent("xy");
3997
this.subscribe("hide", restoreOriginalWidth, [(sOriginalWidth || ""), sNewWidth]);
4001
// "onDOMReady" that renders the ToolTip
4003
function onDOMReady(p_sType, p_aArgs, p_oObject) {
4004
this.render(p_oObject);
4007
// "init" event handler that automatically renders the Tooltip
4010
Event.onDOMReady(onDOMReady, this.cfg.getProperty("container"), this);
4013
YAHOO.extend(Tooltip, YAHOO.widget.Overlay, {
4016
* The Tooltip initialization method. This method is automatically
4017
* called by the constructor. A Tooltip is automatically rendered by
4018
* the init method, and it also is set to be invisible by default,
4019
* and constrained to viewport by default as well.
4021
* @param {String} el The element ID representing the Tooltip <em>OR</em>
4022
* @param {HTMLElement} el The element representing the Tooltip
4023
* @param {Object} userConfig The configuration object literal
4024
* containing the configuration that should be set for this Tooltip.
4025
* See configuration documentation for more details.
4027
init: function (el, userConfig) {
4030
Tooltip.superclass.init.call(this, el);
4032
this.beforeInitEvent.fire(Tooltip);
4034
Dom.addClass(this.element, Tooltip.CSS_TOOLTIP);
4037
this.cfg.applyConfig(userConfig, true);
4040
this.cfg.queueProperty("visible", false);
4041
this.cfg.queueProperty("constraintoviewport", true);
4045
this.subscribe("beforeShow", setWidthToOffsetWidth);
4046
this.subscribe("init", onInit);
4047
this.subscribe("render", this.onRender);
4049
this.initEvent.fire(Tooltip);
4053
* Initializes the custom events for Tooltip
4054
* @method initEvents
4056
initEvents: function () {
4058
Tooltip.superclass.initEvents.call(this);
4059
var SIGNATURE = CustomEvent.LIST;
4062
* CustomEvent fired when user mouses over a context element. Returning false from
4063
* a subscriber to this event will prevent the tooltip from being displayed for
4064
* the current context element.
4066
* @event contextMouseOverEvent
4067
* @param {HTMLElement} context The context element which the user just moused over
4068
* @param {DOMEvent} e The DOM event object, associated with the mouse over
4070
this.contextMouseOverEvent = this.createEvent(EVENT_TYPES.CONTEXT_MOUSE_OVER);
4071
this.contextMouseOverEvent.signature = SIGNATURE;
4074
* CustomEvent fired when the user mouses out of a context element.
4076
* @event contextMouseOutEvent
4077
* @param {HTMLElement} context The context element which the user just moused out of
4078
* @param {DOMEvent} e The DOM event object, associated with the mouse out
4080
this.contextMouseOutEvent = this.createEvent(EVENT_TYPES.CONTEXT_MOUSE_OUT);
4081
this.contextMouseOutEvent.signature = SIGNATURE;
4084
* CustomEvent fired just before the tooltip is displayed for the current context.
4086
* You can subscribe to this event if you need to set up the text for the
4087
* tooltip based on the context element for which it is about to be displayed.
4089
* <p>This event differs from the beforeShow event in following respects:</p>
4092
* When moving from one context element to another, if the tooltip is not
4093
* hidden (the <code>hidedelay</code> is not reached), the beforeShow and Show events will not
4094
* be fired when the tooltip is displayed for the new context since it is already visible.
4095
* However the contextTrigger event is always fired before displaying the tooltip for
4099
* The trigger event provides access to the context element, allowing you to
4100
* set the text of the tooltip based on context element for which the tooltip is
4105
* It is not possible to prevent the tooltip from being displayed
4106
* using this event. You can use the contextMouseOverEvent if you need to prevent
4107
* the tooltip from being displayed.
4109
* @event contextTriggerEvent
4110
* @param {HTMLElement} context The context element for which the tooltip is triggered
4112
this.contextTriggerEvent = this.createEvent(EVENT_TYPES.CONTEXT_TRIGGER);
4113
this.contextTriggerEvent.signature = SIGNATURE;
4117
* Initializes the class's configurable properties which can be
4118
* changed using the Overlay's Config object (cfg).
4119
* @method initDefaultConfig
4121
initDefaultConfig: function () {
4123
Tooltip.superclass.initDefaultConfig.call(this);
4126
* Specifies whether the Tooltip should be kept from overlapping
4127
* its context element.
4128
* @config preventoverlap
4132
this.cfg.addProperty(DEFAULT_CONFIG.PREVENT_OVERLAP.key, {
4133
value: DEFAULT_CONFIG.PREVENT_OVERLAP.value,
4134
validator: DEFAULT_CONFIG.PREVENT_OVERLAP.validator,
4135
supercedes: DEFAULT_CONFIG.PREVENT_OVERLAP.supercedes
4139
* The number of milliseconds to wait before showing a Tooltip
4145
this.cfg.addProperty(DEFAULT_CONFIG.SHOW_DELAY.key, {
4146
handler: this.configShowDelay,
4148
validator: DEFAULT_CONFIG.SHOW_DELAY.validator
4152
* The number of milliseconds to wait before automatically
4153
* dismissing a Tooltip after the mouse has been resting on the
4155
* @config autodismissdelay
4159
this.cfg.addProperty(DEFAULT_CONFIG.AUTO_DISMISS_DELAY.key, {
4160
handler: this.configAutoDismissDelay,
4161
value: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.value,
4162
validator: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.validator
4166
* The number of milliseconds to wait before hiding a Tooltip
4172
this.cfg.addProperty(DEFAULT_CONFIG.HIDE_DELAY.key, {
4173
handler: this.configHideDelay,
4174
value: DEFAULT_CONFIG.HIDE_DELAY.value,
4175
validator: DEFAULT_CONFIG.HIDE_DELAY.validator
4179
* Specifies the Tooltip's text.
4184
this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, {
4185
handler: this.configText,
4186
suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent
4190
* Specifies the container element that the Tooltip's markup
4191
* should be rendered into.
4193
* @type HTMLElement/String
4194
* @default document.body
4196
this.cfg.addProperty(DEFAULT_CONFIG.CONTAINER.key, {
4197
handler: this.configContainer,
4198
value: document.body
4202
* Specifies whether or not the tooltip is disabled. Disabled tooltips
4203
* will not be displayed. If the tooltip is driven by the title attribute
4204
* of the context element, the title attribute will still be removed for
4205
* disabled tooltips, to prevent default tooltip behavior.
4211
this.cfg.addProperty(DEFAULT_CONFIG.DISABLED.key, {
4212
handler: this.configContainer,
4213
value: DEFAULT_CONFIG.DISABLED.value,
4214
supressEvent: DEFAULT_CONFIG.DISABLED.suppressEvent
4218
* Specifies the element or elements that the Tooltip should be
4219
* anchored to on mouseover.
4221
* @type HTMLElement[]/String[]
4226
* String representing the width of the Tooltip. <em>Please note:
4227
* </em> As of version 2.3 if either no value or a value of "auto"
4228
* is specified, and the Toolip's "container" configuration property
4229
* is set to something other than <code>document.body</code> or
4230
* its "context" element resides outside the immediately visible
4231
* portion of the document, the width of the Tooltip will be
4232
* calculated based on the offsetWidth of its root HTML and set just
4233
* before it is made visible. The original value will be
4234
* restored when the Tooltip is hidden. This ensures the Tooltip is
4235
* rendered at a usable width. For more information see
4236
* SourceForge bug #1685496 and SourceForge
4245
// BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
4248
* The default event handler fired when the "text" property is changed.
4249
* @method configText
4250
* @param {String} type The CustomEvent type (usually the property name)
4251
* @param {Object[]} args The CustomEvent arguments. For configuration
4252
* handlers, args[0] will equal the newly applied value for the property.
4253
* @param {Object} obj The scope object. For configuration handlers,
4254
* this will usually equal the owner.
4256
configText: function (type, args, obj) {
4264
* The default event handler fired when the "container" property
4266
* @method configContainer
4267
* @param {String} type The CustomEvent type (usually the property name)
4268
* @param {Object[]} args The CustomEvent arguments. For
4269
* configuration handlers, args[0] will equal the newly applied value
4271
* @param {Object} obj The scope object. For configuration handlers,
4272
* this will usually equal the owner.
4274
configContainer: function (type, args, obj) {
4275
var container = args[0];
4277
if (typeof container == 'string') {
4278
this.cfg.setProperty("container", document.getElementById(container), true);
4283
* @method _removeEventListeners
4284
* @description Removes all of the DOM event handlers from the HTML
4285
* element(s) that trigger the display of the tooltip.
4288
_removeEventListeners: function () {
4290
var aElements = this._context,
4296
nElements = aElements.length;
4297
if (nElements > 0) {
4300
oElement = aElements[i];
4301
Event.removeListener(oElement, "mouseover", this.onContextMouseOver);
4302
Event.removeListener(oElement, "mousemove", this.onContextMouseMove);
4303
Event.removeListener(oElement, "mouseout", this.onContextMouseOut);
4311
* The default event handler fired when the "context" property
4313
* @method configContext
4314
* @param {String} type The CustomEvent type (usually the property name)
4315
* @param {Object[]} args The CustomEvent arguments. For configuration
4316
* handlers, args[0] will equal the newly applied value for the property.
4317
* @param {Object} obj The scope object. For configuration handlers,
4318
* this will usually equal the owner.
4320
configContext: function (type, args, obj) {
4322
var context = args[0],
4330
// Normalize parameter into an array
4331
if (! (context instanceof Array)) {
4332
if (typeof context == "string") {
4333
this.cfg.setProperty("context", [document.getElementById(context)], true);
4334
} else { // Assuming this is an element
4335
this.cfg.setProperty("context", [context], true);
4337
context = this.cfg.getProperty("context");
4340
// Remove any existing mouseover/mouseout listeners
4341
this._removeEventListeners();
4343
// Add mouseover/mouseout listeners to context elements
4344
this._context = context;
4346
aElements = this._context;
4349
nElements = aElements.length;
4350
if (nElements > 0) {
4353
oElement = aElements[i];
4354
Event.on(oElement, "mouseover", this.onContextMouseOver, this);
4355
Event.on(oElement, "mousemove", this.onContextMouseMove, this);
4356
Event.on(oElement, "mouseout", this.onContextMouseOut, this);
4364
// END BUILT-IN PROPERTY EVENT HANDLERS //
4366
// BEGIN BUILT-IN DOM EVENT HANDLERS //
4369
* The default event handler fired when the user moves the mouse while
4370
* over the context element.
4371
* @method onContextMouseMove
4372
* @param {DOMEvent} e The current DOM event
4373
* @param {Object} obj The object argument
4375
onContextMouseMove: function (e, obj) {
4376
obj.pageX = Event.getPageX(e);
4377
obj.pageY = Event.getPageY(e);
4381
* The default event handler fired when the user mouses over the
4383
* @method onContextMouseOver
4384
* @param {DOMEvent} e The current DOM event
4385
* @param {Object} obj The object argument
4387
onContextMouseOver: function (e, obj) {
4390
if (context.title) {
4391
obj._tempTitle = context.title;
4395
// Fire first, to honor disabled set in the listner
4396
if (obj.fireEvent("contextMouseOver", context, e) !== false
4397
&& !obj.cfg.getProperty("disabled")) {
4399
// Stop the tooltip from being hidden (set on last mouseout)
4400
if (obj.hideProcId) {
4401
clearTimeout(obj.hideProcId);
4402
obj.hideProcId = null;
4405
Event.on(context, "mousemove", obj.onContextMouseMove, obj);
4408
* The unique process ID associated with the thread responsible
4409
* for showing the Tooltip.
4412
obj.showProcId = obj.doShow(e, context);
4417
* The default event handler fired when the user mouses out of
4418
* the context element.
4419
* @method onContextMouseOut
4420
* @param {DOMEvent} e The current DOM event
4421
* @param {Object} obj The object argument
4423
onContextMouseOut: function (e, obj) {
4426
if (obj._tempTitle) {
4427
el.title = obj._tempTitle;
4428
obj._tempTitle = null;
4431
if (obj.showProcId) {
4432
clearTimeout(obj.showProcId);
4433
obj.showProcId = null;
4436
if (obj.hideProcId) {
4437
clearTimeout(obj.hideProcId);
4438
obj.hideProcId = null;
4441
obj.fireEvent("contextMouseOut", el, e);
4443
obj.hideProcId = setTimeout(function () {
4445
}, obj.cfg.getProperty("hidedelay"));
4448
// END BUILT-IN DOM EVENT HANDLERS //
4451
* Processes the showing of the Tooltip by setting the timeout delay
4452
* and offset of the Tooltip.
4454
* @param {DOMEvent} e The current DOM event
4455
* @return {Number} The process ID of the timeout function associated
4458
doShow: function (e, context) {
4463
if (YAHOO.env.ua.opera && context.tagName &&
4464
context.tagName.toUpperCase() == "A") {
4468
return setTimeout(function () {
4470
var txt = me.cfg.getProperty("text");
4472
// title does not over-ride text
4473
if (me._tempTitle && (txt === "" || YAHOO.lang.isUndefined(txt) || YAHOO.lang.isNull(txt))) {
4474
me.setBody(me._tempTitle);
4476
me.cfg.refireEvent("text");
4479
me.moveTo(me.pageX, me.pageY + yOffset);
4481
if (me.cfg.getProperty("preventoverlap")) {
4482
me.preventOverlap(me.pageX, me.pageY);
4485
Event.removeListener(context, "mousemove", me.onContextMouseMove);
4487
me.contextTriggerEvent.fire(context);
4491
me.hideProcId = me.doHide();
4493
}, this.cfg.getProperty("showdelay"));
4497
* Sets the timeout for the auto-dismiss delay, which by default is 5
4498
* seconds, meaning that a tooltip will automatically dismiss itself
4499
* after 5 seconds of being displayed.
4502
doHide: function () {
4507
return setTimeout(function () {
4511
}, this.cfg.getProperty("autodismissdelay"));
4516
* Fired when the Tooltip is moved, this event handler is used to
4517
* prevent the Tooltip from overlapping with its context element.
4518
* @method preventOverlay
4519
* @param {Number} pageX The x coordinate position of the mouse pointer
4520
* @param {Number} pageY The y coordinate position of the mouse pointer
4522
preventOverlap: function (pageX, pageY) {
4524
var height = this.element.offsetHeight,
4525
mousePoint = new YAHOO.util.Point(pageX, pageY),
4526
elementRegion = Dom.getRegion(this.element);
4528
elementRegion.top -= 5;
4529
elementRegion.left -= 5;
4530
elementRegion.right += 5;
4531
elementRegion.bottom += 5;
4534
if (elementRegion.contains(mousePoint)) {
4535
this.cfg.setProperty("y", (pageY - height - 5));
4542
* @description "render" event handler for the Tooltip.
4543
* @param {String} p_sType String representing the name of the event
4545
* @param {Array} p_aArgs Array of arguments sent when the event
4548
onRender: function (p_sType, p_aArgs) {
4550
function sizeShadow() {
4552
var oElement = this.element,
4553
oShadow = this._shadow;
4556
oShadow.style.width = (oElement.offsetWidth + 6) + "px";
4557
oShadow.style.height = (oElement.offsetHeight + 1) + "px";
4562
function addShadowVisibleClass() {
4563
Dom.addClass(this._shadow, "yui-tt-shadow-visible");
4567
function removeShadowVisibleClass() {
4568
Dom.removeClass(this._shadow, "yui-tt-shadow-visible");
4571
function createShadow() {
4573
var oShadow = this._shadow,
4581
oElement = this.element;
4582
Module = YAHOO.widget.Module;
4583
nIE = YAHOO.env.ua.ie;
4586
if (!m_oShadowTemplate) {
4587
m_oShadowTemplate = document.createElement("div");
4588
m_oShadowTemplate.className = "yui-tt-shadow";
4591
oShadow = m_oShadowTemplate.cloneNode(false);
4593
oElement.appendChild(oShadow);
4595
this._shadow = oShadow;
4597
addShadowVisibleClass.call(this);
4599
this.subscribe("beforeShow", addShadowVisibleClass);
4600
this.subscribe("beforeHide", removeShadowVisibleClass);
4602
if (nIE == 6 || (nIE == 7 && document.compatMode == "BackCompat")) {
4603
window.setTimeout(function () {
4604
sizeShadow.call(me);
4607
this.cfg.subscribeToConfigEvent("width", sizeShadow);
4608
this.cfg.subscribeToConfigEvent("height", sizeShadow);
4609
this.subscribe("changeContent", sizeShadow);
4611
Module.textResizeEvent.subscribe(sizeShadow, this, true);
4612
this.subscribe("destroy", function () {
4613
Module.textResizeEvent.unsubscribe(sizeShadow, this);
4619
function onBeforeShow() {
4620
createShadow.call(this);
4621
this.unsubscribe("beforeShow", onBeforeShow);
4624
if (this.cfg.getProperty("visible")) {
4625
createShadow.call(this);
4627
this.subscribe("beforeShow", onBeforeShow);
4633
* Removes the Tooltip element from the DOM and sets all child
4637
destroy: function () {
4639
// Remove any existing mouseover/mouseout listeners
4640
this._removeEventListeners();
4642
Tooltip.superclass.destroy.call(this);
4647
* Returns a string representation of the object.
4649
* @return {String} The string representation of the Tooltip
4651
toString: function () {
4652
return "Tooltip " + this.id;
4662
* Panel is an implementation of Overlay that behaves like an OS window,
4663
* with a draggable header and an optional close icon at the top right.
4664
* @namespace YAHOO.widget
4666
* @extends YAHOO.widget.Overlay
4668
* @param {String} el The element ID representing the Panel <em>OR</em>
4669
* @param {HTMLElement} el The element representing the Panel
4670
* @param {Object} userConfig The configuration object literal containing
4671
* the configuration that should be set for this Panel. See configuration
4672
* documentation for more details.
4674
YAHOO.widget.Panel = function (el, userConfig) {
4675
YAHOO.widget.Panel.superclass.constructor.call(this, el, userConfig);
4678
var Lang = YAHOO.lang,
4680
Dom = YAHOO.util.Dom,
4681
Event = YAHOO.util.Event,
4682
Overlay = YAHOO.widget.Overlay,
4683
CustomEvent = YAHOO.util.CustomEvent,
4684
Config = YAHOO.util.Config,
4685
Panel = YAHOO.widget.Panel,
4688
m_oUnderlayTemplate,
4689
m_oCloseIconTemplate,
4692
* Constant representing the name of the Panel's events
4693
* @property EVENT_TYPES
4700
"SHOW_MASK": "showMask",
4701
"HIDE_MASK": "hideMask",
4707
* Constant representing the Panel's configuration properties
4708
* @property DEFAULT_CONFIG
4718
validator: Lang.isBoolean,
4719
supercedes: ["visible"]
4724
value: (DD ? true : false),
4725
validator: Lang.isBoolean,
4726
supercedes: ["visible"]
4732
validator: Lang.isBoolean,
4733
supercedes: ["draggable"]
4739
supercedes: ["visible"]
4745
validator: Lang.isBoolean,
4746
supercedes: ["visible", "zindex"]
4750
key: "keylisteners",
4751
suppressEvent: true,
4752
supercedes: ["visible"]
4757
* Constant representing the default CSS class used for a Panel
4758
* @property YAHOO.widget.Panel.CSS_PANEL
4763
Panel.CSS_PANEL = "yui-panel";
4766
* Constant representing the default CSS class used for a Panel's
4767
* wrapping container
4768
* @property YAHOO.widget.Panel.CSS_PANEL_CONTAINER
4773
Panel.CSS_PANEL_CONTAINER = "yui-panel-container";
4775
// Private CustomEvent listeners
4778
"beforeRender" event handler that creates an empty header for a Panel
4779
instance if its "draggable" configuration property is set to "true"
4780
and no header has been created.
4783
function createHeader(p_sType, p_aArgs) {
4784
if (!this.header && this.cfg.getProperty("draggable")) {
4785
this.setHeader(" ");
4790
"hide" event handler that sets a Panel instance's "width"
4791
configuration property back to its original value before
4792
"setWidthToOffsetWidth" was called.
4795
function restoreOriginalWidth(p_sType, p_aArgs, p_oObject) {
4797
var sOriginalWidth = p_oObject[0],
4798
sNewWidth = p_oObject[1],
4800
sCurrentWidth = oConfig.getProperty("width");
4802
if (sCurrentWidth == sNewWidth) {
4803
oConfig.setProperty("width", sOriginalWidth);
4806
this.unsubscribe("hide", restoreOriginalWidth, p_oObject);
4810
"beforeShow" event handler that sets a Panel instance's "width"
4811
configuration property to the value of its root HTML
4812
elements's offsetWidth
4815
function setWidthToOffsetWidth(p_sType, p_aArgs) {
4817
var nIE = YAHOO.env.ua.ie,
4822
if (nIE == 6 || (nIE == 7 && document.compatMode == "BackCompat")) {
4825
sOriginalWidth = oConfig.getProperty("width");
4827
if (!sOriginalWidth || sOriginalWidth == "auto") {
4829
sNewWidth = (this.element.offsetWidth + "px");
4831
oConfig.setProperty("width", sNewWidth);
4833
this.subscribe("hide", restoreOriginalWidth,
4834
[(sOriginalWidth || ""), sNewWidth]);
4841
"focus" event handler for a focuable element. Used to automatically
4842
blur the element when it receives focus to ensure that a Panel
4843
instance's modality is not compromised.
4846
function onElementFocus() {
4851
"showMask" event handler that adds a "focus" event handler to all
4852
focusable elements in the document to enforce a Panel instance's
4853
modality from being compromised.
4856
function addFocusEventHandlers(p_sType, p_aArgs) {
4860
function isFocusable(el) {
4862
var sTagName = el.tagName.toUpperCase(),
4872
if (!Dom.isAncestor(me.element, el)) {
4873
Event.on(el, "focus", onElementFocus, el, true);
4881
if (el.type != "hidden" &&
4882
!Dom.isAncestor(me.element, el)) {
4884
Event.on(el, "focus", onElementFocus, el, true);
4897
this.focusableElements = Dom.getElementsBy(isFocusable);
4902
"hideMask" event handler that removes all "focus" event handlers added
4903
by the "addFocusEventHandlers" method.
4906
function removeFocusEventHandlers(p_sType, p_aArgs) {
4908
var aElements = this.focusableElements,
4909
nElements = aElements.length,
4913
for (i = 0; i < nElements; i++) {
4915
Event.removeListener(el2, "focus", onElementFocus);
4920
YAHOO.extend(Panel, Overlay, {
4923
* The Overlay initialization method, which is executed for Overlay and
4924
* all of its subclasses. This method is automatically called by the
4925
* constructor, and sets up all DOM references for pre-existing markup,
4926
* and creates required markup if it is not already present.
4928
* @param {String} el The element ID representing the Overlay <em>OR</em>
4929
* @param {HTMLElement} el The element representing the Overlay
4930
* @param {Object} userConfig The configuration object literal
4931
* containing the configuration that should be set for this Overlay.
4932
* See configuration documentation for more details.
4934
init: function (el, userConfig) {
4937
Note that we don't pass the user config in here yet because
4938
we only want it executed once, at the lowest subclass level
4941
Panel.superclass.init.call(this, el/*, userConfig*/);
4943
this.beforeInitEvent.fire(Panel);
4945
Dom.addClass(this.element, Panel.CSS_PANEL);
4947
this.buildWrapper();
4950
this.cfg.applyConfig(userConfig, true);
4953
this.subscribe("showMask", addFocusEventHandlers);
4954
this.subscribe("hideMask", removeFocusEventHandlers);
4955
this.subscribe("beforeRender", createHeader);
4957
this.initEvent.fire(Panel);
4961
* Initializes the custom events for Module which are fired
4962
* automatically at appropriate times by the Module class.
4964
initEvents: function () {
4965
Panel.superclass.initEvents.call(this);
4967
var SIGNATURE = CustomEvent.LIST;
4970
* CustomEvent fired after the modality mask is shown
4971
* @event showMaskEvent
4973
this.showMaskEvent = this.createEvent(EVENT_TYPES.SHOW_MASK);
4974
this.showMaskEvent.signature = SIGNATURE;
4977
* CustomEvent fired after the modality mask is hidden
4978
* @event hideMaskEvent
4980
this.hideMaskEvent = this.createEvent(EVENT_TYPES.HIDE_MASK);
4981
this.hideMaskEvent.signature = SIGNATURE;
4984
* CustomEvent when the Panel is dragged
4987
this.dragEvent = this.createEvent(EVENT_TYPES.DRAG);
4988
this.dragEvent.signature = SIGNATURE;
4993
* Initializes the class's configurable properties which can be changed
4994
* using the Panel's Config object (cfg).
4995
* @method initDefaultConfig
4997
initDefaultConfig: function () {
4998
Panel.superclass.initDefaultConfig.call(this);
5000
// Add panel config properties //
5003
* True if the Panel should display a "close" button
5008
this.cfg.addProperty(DEFAULT_CONFIG.CLOSE.key, {
5009
handler: this.configClose,
5010
value: DEFAULT_CONFIG.CLOSE.value,
5011
validator: DEFAULT_CONFIG.CLOSE.validator,
5012
supercedes: DEFAULT_CONFIG.CLOSE.supercedes
5016
* Boolean specifying if the Panel should be draggable. The default
5017
* value is "true" if the Drag and Drop utility is included,
5018
* otherwise it is "false." <strong>PLEASE NOTE:</strong> There is a
5019
* known issue in IE 6 (Strict Mode and Quirks Mode) and IE 7
5020
* (Quirks Mode) where Panels that either don't have a value set for
5021
* their "width" configuration property, or their "width"
5022
* configuration property is set to "auto" will only be draggable by
5023
* placing the mouse on the text of the Panel's header element.
5024
* To fix this bug, draggable Panels missing a value for their
5025
* "width" configuration property, or whose "width" configuration
5026
* property is set to "auto" will have it set to the value of
5027
* their root HTML element's offsetWidth before they are made
5028
* visible. The calculated width is then removed when the Panel is
5029
* hidden. <em>This fix is only applied to draggable Panels in IE 6
5030
* (Strict Mode and Quirks Mode) and IE 7 (Quirks Mode)</em>. For
5031
* more information on this issue see:
5032
* SourceForge bugs #1726972 and #1589210.
5037
this.cfg.addProperty(DEFAULT_CONFIG.DRAGGABLE.key, {
5038
handler: this.configDraggable,
5039
value: DEFAULT_CONFIG.DRAGGABLE.value,
5040
validator: DEFAULT_CONFIG.DRAGGABLE.validator,
5041
supercedes: DEFAULT_CONFIG.DRAGGABLE.supercedes
5045
* Boolean specifying if the draggable Panel should be drag only, not interacting with drop
5046
* targets on the page.
5048
* When set to true, draggable Panels will not check to see if they are over drop targets,
5049
* or fire the DragDrop events required to support drop target interaction (onDragEnter,
5050
* onDragOver, onDragOut, onDragDrop etc.).
5051
* If the Panel is not designed to be dropped on any target elements on the page, then this
5052
* flag can be set to true to improve performance.
5055
* When set to false, all drop target related events will be fired.
5058
* The property is set to false by default to maintain backwards compatibility but should be
5059
* set to true if drop target interaction is not required for the Panel, to improve performance.</p>
5065
this.cfg.addProperty(DEFAULT_CONFIG.DRAG_ONLY.key, {
5066
value: DEFAULT_CONFIG.DRAG_ONLY.value,
5067
validator: DEFAULT_CONFIG.DRAG_ONLY.validator,
5068
supercedes: DEFAULT_CONFIG.DRAG_ONLY.supercedes
5072
* Sets the type of underlay to display for the Panel. Valid values
5073
* are "shadow," "matte," and "none". <strong>PLEASE NOTE:</strong>
5074
* The creation of the underlay element is deferred until the Panel
5075
* is initially made visible. For Gecko-based browsers on Mac
5076
* OS X the underlay elment is always created as it is used as a
5077
* shim to prevent Aqua scrollbars below a Panel instance from poking
5078
* through it (See SourceForge bug #836476).
5083
this.cfg.addProperty(DEFAULT_CONFIG.UNDERLAY.key, {
5084
handler: this.configUnderlay,
5085
value: DEFAULT_CONFIG.UNDERLAY.value,
5086
supercedes: DEFAULT_CONFIG.UNDERLAY.supercedes
5090
* True if the Panel should be displayed in a modal fashion,
5091
* automatically creating a transparent mask over the document that
5092
* will not be removed until the Panel is dismissed.
5097
this.cfg.addProperty(DEFAULT_CONFIG.MODAL.key, {
5098
handler: this.configModal,
5099
value: DEFAULT_CONFIG.MODAL.value,
5100
validator: DEFAULT_CONFIG.MODAL.validator,
5101
supercedes: DEFAULT_CONFIG.MODAL.supercedes
5105
* A KeyListener (or array of KeyListeners) that will be enabled
5106
* when the Panel is shown, and disabled when the Panel is hidden.
5107
* @config keylisteners
5108
* @type YAHOO.util.KeyListener[]
5111
this.cfg.addProperty(DEFAULT_CONFIG.KEY_LISTENERS.key, {
5112
handler: this.configKeyListeners,
5113
suppressEvent: DEFAULT_CONFIG.KEY_LISTENERS.suppressEvent,
5114
supercedes: DEFAULT_CONFIG.KEY_LISTENERS.supercedes
5119
// BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
5122
* The default event handler fired when the "close" property is changed.
5123
* The method controls the appending or hiding of the close icon at the
5124
* top right of the Panel.
5125
* @method configClose
5126
* @param {String} type The CustomEvent type (usually the property name)
5127
* @param {Object[]} args The CustomEvent arguments. For configuration
5128
* handlers, args[0] will equal the newly applied value for the property.
5129
* @param {Object} obj The scope object. For configuration handlers,
5130
* this will usually equal the owner.
5132
configClose: function (type, args, obj) {
5135
oClose = this.close;
5137
function doHide(e, obj) {
5143
if (!m_oCloseIconTemplate) {
5144
m_oCloseIconTemplate = document.createElement("span");
5145
m_oCloseIconTemplate.innerHTML = " ";
5146
m_oCloseIconTemplate.className = "container-close";
5149
oClose = m_oCloseIconTemplate.cloneNode(true);
5150
this.innerElement.appendChild(oClose);
5151
Event.on(oClose, "click", doHide, this);
5153
this.close = oClose;
5156
oClose.style.display = "block";
5161
oClose.style.display = "none";
5168
* The default event handler fired when the "draggable" property
5170
* @method configDraggable
5171
* @param {String} type The CustomEvent type (usually the property name)
5172
* @param {Object[]} args The CustomEvent arguments. For configuration
5173
* handlers, args[0] will equal the newly applied value for the property.
5174
* @param {Object} obj The scope object. For configuration handlers,
5175
* this will usually equal the owner.
5177
configDraggable: function (type, args, obj) {
5182
this.cfg.setProperty("draggable", false);
5187
Dom.setStyle(this.header, "cursor", "move");
5188
this.registerDragDrop();
5191
this.subscribe("beforeShow", setWidthToOffsetWidth);
5200
Dom.setStyle(this.header,"cursor","auto");
5203
this.unsubscribe("beforeShow", setWidthToOffsetWidth);
5208
* The default event handler fired when the "underlay" property
5210
* @method configUnderlay
5211
* @param {String} type The CustomEvent type (usually the property name)
5212
* @param {Object[]} args The CustomEvent arguments. For configuration
5213
* handlers, args[0] will equal the newly applied value for the property.
5214
* @param {Object} obj The scope object. For configuration handlers,
5215
* this will usually equal the owner.
5217
configUnderlay: function (type, args, obj) {
5219
var UA = YAHOO.env.ua,
5220
bMacGecko = (this.platform == "mac" && UA.gecko),
5221
bIEQuirks = (UA.ie == 6 || (UA.ie == 7 && document.compatMode == "BackCompat")),
5222
sUnderlay = args[0].toLowerCase(),
5223
oUnderlay = this.underlay,
5224
oElement = this.element;
5226
function fixWebkitUnderlay() {
5227
// Webkit 419.3 (Safari 2.x) does not update
5228
// it's Render Tree for the Container when content changes.
5229
// We need to force it to update using this contentChange
5232
// Webkit 523.6 doesn't have this problem and doesn't
5234
var u = this.underlay;
5235
Dom.addClass(u, "yui-force-redraw");
5236
window.setTimeout(function(){Dom.removeClass(u, "yui-force-redraw");}, 0);
5239
function createUnderlay() {
5241
if (!oUnderlay) { // create if not already in DOM
5243
if (!m_oUnderlayTemplate) {
5244
m_oUnderlayTemplate = document.createElement("div");
5245
m_oUnderlayTemplate.className = "underlay";
5248
oUnderlay = m_oUnderlayTemplate.cloneNode(false);
5249
this.element.appendChild(oUnderlay);
5251
this.underlay = oUnderlay;
5254
this.sizeUnderlay();
5255
this.cfg.subscribeToConfigEvent("width", this.sizeUnderlay);
5256
this.cfg.subscribeToConfigEvent("height",this.sizeUnderlay);
5257
this.changeContentEvent.subscribe(this.sizeUnderlay);
5258
YAHOO.widget.Module.textResizeEvent.subscribe(this.sizeUnderlay, this, true);
5261
if (UA.webkit && UA.webkit < 420) {
5262
this.changeContentEvent.subscribe(fixWebkitUnderlay);
5268
function onBeforeShow() {
5269
var bNew = createUnderlay.call(this);
5270
if (!bNew && bIEQuirks) {
5271
this.sizeUnderlay();
5273
this._underlayDeferred = false;
5274
this.beforeShowEvent.unsubscribe(onBeforeShow);
5277
function destroyUnderlay() {
5278
if (this._underlayDeferred) {
5279
this.beforeShowEvent.unsubscribe(onBeforeShow);
5280
this._underlayDeferred = false;
5284
this.cfg.unsubscribeFromConfigEvent("width", this.sizeUnderlay);
5285
this.cfg.unsubscribeFromConfigEvent("height",this.sizeUnderlay);
5286
this.changeContentEvent.unsubscribe(this.sizeUnderlay);
5287
this.changeContentEvent.unsubscribe(fixWebkitUnderlay);
5288
YAHOO.widget.Module.textResizeEvent.unsubscribe(this.sizeUnderlay, this, true);
5290
this.element.removeChild(oUnderlay);
5292
this.underlay = null;
5296
switch (sUnderlay) {
5298
Dom.removeClass(oElement, "matte");
5299
Dom.addClass(oElement, "shadow");
5303
destroyUnderlay.call(this);
5305
Dom.removeClass(oElement, "shadow");
5306
Dom.addClass(oElement, "matte");
5310
destroyUnderlay.call(this);
5312
Dom.removeClass(oElement, "shadow");
5313
Dom.removeClass(oElement, "matte");
5317
if ((sUnderlay == "shadow") || (bMacGecko && !oUnderlay)) {
5318
if (this.cfg.getProperty("visible")) {
5319
var bNew = createUnderlay.call(this);
5320
if (!bNew && bIEQuirks) {
5321
this.sizeUnderlay();
5324
if (!this._underlayDeferred) {
5325
this.beforeShowEvent.subscribe(onBeforeShow);
5326
this._underlayDeferred = true;
5333
* The default event handler fired when the "modal" property is
5334
* changed. This handler subscribes or unsubscribes to the show and hide
5335
* events to handle the display or hide of the modality mask.
5336
* @method configModal
5337
* @param {String} type The CustomEvent type (usually the property name)
5338
* @param {Object[]} args The CustomEvent arguments. For configuration
5339
* handlers, args[0] will equal the newly applied value for the property.
5340
* @param {Object} obj The scope object. For configuration handlers,
5341
* this will usually equal the owner.
5343
configModal: function (type, args, obj) {
5345
var modal = args[0];
5347
if (!this._hasModalityEventListeners) {
5349
this.subscribe("beforeShow", this.buildMask);
5350
this.subscribe("beforeShow", this.bringToTop);
5351
this.subscribe("beforeShow", this.showMask);
5352
this.subscribe("hide", this.hideMask);
5354
Overlay.windowResizeEvent.subscribe(this.sizeMask,
5357
this._hasModalityEventListeners = true;
5360
if (this._hasModalityEventListeners) {
5362
if (this.cfg.getProperty("visible")) {
5367
this.unsubscribe("beforeShow", this.buildMask);
5368
this.unsubscribe("beforeShow", this.bringToTop);
5369
this.unsubscribe("beforeShow", this.showMask);
5370
this.unsubscribe("hide", this.hideMask);
5372
Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
5374
this._hasModalityEventListeners = false;
5380
* Removes the modality mask.
5381
* @method removeMask
5383
removeMask: function () {
5385
var oMask = this.mask,
5390
Hide the mask before destroying it to ensure that DOM
5391
event handlers on focusable elements get removed.
5395
oParentNode = oMask.parentNode;
5397
oParentNode.removeChild(oMask);
5405
* The default event handler fired when the "keylisteners" property
5407
* @method configKeyListeners
5408
* @param {String} type The CustomEvent type (usually the property name)
5409
* @param {Object[]} args The CustomEvent arguments. For configuration
5410
* handlers, args[0] will equal the newly applied value for the property.
5411
* @param {Object} obj The scope object. For configuration handlers,
5412
* this will usually equal the owner.
5414
configKeyListeners: function (type, args, obj) {
5416
var listeners = args[0],
5423
if (listeners instanceof Array) {
5425
nListeners = listeners.length;
5427
for (i = 0; i < nListeners; i++) {
5429
listener = listeners[i];
5431
if (!Config.alreadySubscribed(this.showEvent,
5432
listener.enable, listener)) {
5434
this.showEvent.subscribe(listener.enable,
5439
if (!Config.alreadySubscribed(this.hideEvent,
5440
listener.disable, listener)) {
5442
this.hideEvent.subscribe(listener.disable,
5445
this.destroyEvent.subscribe(listener.disable,
5453
if (!Config.alreadySubscribed(this.showEvent,
5454
listeners.enable, listeners)) {
5456
this.showEvent.subscribe(listeners.enable,
5460
if (!Config.alreadySubscribed(this.hideEvent,
5461
listeners.disable, listeners)) {
5463
this.hideEvent.subscribe(listeners.disable,
5466
this.destroyEvent.subscribe(listeners.disable,
5478
* The default event handler fired when the "height" property is changed.
5479
* @method configHeight
5480
* @param {String} type The CustomEvent type (usually the property name)
5481
* @param {Object[]} args The CustomEvent arguments. For configuration
5482
* handlers, args[0] will equal the newly applied value for the property.
5483
* @param {Object} obj The scope object. For configuration handlers,
5484
* this will usually equal the owner.
5486
configHeight: function (type, args, obj) {
5488
var height = args[0],
5489
el = this.innerElement;
5491
Dom.setStyle(el, "height", height);
5492
this.cfg.refireEvent("iframe");
5497
* The default event handler fired when the "width" property is changed.
5498
* @method configWidth
5499
* @param {String} type The CustomEvent type (usually the property name)
5500
* @param {Object[]} args The CustomEvent arguments. For configuration
5501
* handlers, args[0] will equal the newly applied value for the property.
5502
* @param {Object} obj The scope object. For configuration handlers,
5503
* this will usually equal the owner.
5505
configWidth: function (type, args, obj) {
5507
var width = args[0],
5508
el = this.innerElement;
5510
Dom.setStyle(el, "width", width);
5511
this.cfg.refireEvent("iframe");
5516
* The default event handler fired when the "zIndex" property is changed.
5517
* @method configzIndex
5518
* @param {String} type The CustomEvent type (usually the property name)
5519
* @param {Object[]} args The CustomEvent arguments. For configuration
5520
* handlers, args[0] will equal the newly applied value for the property.
5521
* @param {Object} obj The scope object. For configuration handlers,
5522
* this will usually equal the owner.
5524
configzIndex: function (type, args, obj) {
5525
Panel.superclass.configzIndex.call(this, type, args, obj);
5527
if (this.mask || this.cfg.getProperty("modal") === true) {
5528
var panelZ = Dom.getStyle(this.element, "zIndex");
5529
if (!panelZ || isNaN(panelZ)) {
5534
// Recursive call to configzindex (which should be stopped
5535
// from going further because panelZ should no longer === 0)
5536
this.cfg.setProperty("zIndex", 1);
5543
// END BUILT-IN PROPERTY EVENT HANDLERS //
5545
* Builds the wrapping container around the Panel that is used for
5546
* positioning the shadow and matte underlays. The container element is
5547
* assigned to a local instance variable called container, and the
5548
* element is reinserted inside of it.
5549
* @method buildWrapper
5551
buildWrapper: function () {
5553
var elementParent = this.element.parentNode,
5554
originalElement = this.element,
5555
wrapper = document.createElement("div");
5557
wrapper.className = Panel.CSS_PANEL_CONTAINER;
5558
wrapper.id = originalElement.id + "_c";
5560
if (elementParent) {
5561
elementParent.insertBefore(wrapper, originalElement);
5564
wrapper.appendChild(originalElement);
5566
this.element = wrapper;
5567
this.innerElement = originalElement;
5569
Dom.setStyle(this.innerElement, "visibility", "inherit");
5573
* Adjusts the size of the shadow based on the size of the element.
5574
* @method sizeUnderlay
5576
sizeUnderlay: function () {
5577
var oUnderlay = this.underlay,
5581
oElement = this.element;
5582
oUnderlay.style.width = oElement.offsetWidth + "px";
5583
oUnderlay.style.height = oElement.offsetHeight + "px";
5589
* Registers the Panel's header for drag & drop capability.
5590
* @method registerDragDrop
5592
registerDragDrop: function () {
5602
var bDragOnly = (this.cfg.getProperty("dragonly") === true);
5603
this.dd = new DD(this.element.id, this.id, {dragOnly: bDragOnly});
5605
if (!this.header.id) {
5606
this.header.id = this.id + "_h";
5609
this.dd.startDrag = function () {
5618
if (YAHOO.env.ua.ie == 6) {
5619
Dom.addClass(me.element,"drag");
5622
if (me.cfg.getProperty("constraintoviewport")) {
5624
var nViewportOffset = Overlay.VIEWPORT_OFFSET;
5626
offsetHeight = me.element.offsetHeight;
5627
offsetWidth = me.element.offsetWidth;
5629
viewPortWidth = Dom.getViewportWidth();
5630
viewPortHeight = Dom.getViewportHeight();
5632
scrollX = Dom.getDocumentScrollLeft();
5633
scrollY = Dom.getDocumentScrollTop();
5635
if (offsetHeight + nViewportOffset < viewPortHeight) {
5636
this.minY = scrollY + nViewportOffset;
5637
this.maxY = scrollY + viewPortHeight - offsetHeight - nViewportOffset;
5639
this.minY = scrollY + nViewportOffset;
5640
this.maxY = scrollY + nViewportOffset;
5643
if (offsetWidth + nViewportOffset < viewPortWidth) {
5644
this.minX = scrollX + nViewportOffset;
5645
this.maxX = scrollX + viewPortWidth - offsetWidth - nViewportOffset;
5647
this.minX = scrollX + nViewportOffset;
5648
this.maxX = scrollX + nViewportOffset;
5651
this.constrainX = true;
5652
this.constrainY = true;
5654
this.constrainX = false;
5655
this.constrainY = false;
5658
me.dragEvent.fire("startDrag", arguments);
5661
this.dd.onDrag = function () {
5663
me.cfg.refireEvent("iframe");
5664
if (this.platform == "mac" && YAHOO.env.ua.gecko) {
5665
this.showMacGeckoScrollbars();
5668
me.dragEvent.fire("onDrag", arguments);
5671
this.dd.endDrag = function () {
5673
if (YAHOO.env.ua.ie == 6) {
5674
Dom.removeClass(me.element,"drag");
5677
me.dragEvent.fire("endDrag", arguments);
5678
me.moveEvent.fire(me.cfg.getProperty("xy"));
5682
this.dd.setHandleElId(this.header.id);
5683
this.dd.addInvalidHandleType("INPUT");
5684
this.dd.addInvalidHandleType("SELECT");
5685
this.dd.addInvalidHandleType("TEXTAREA");
5690
* Builds the mask that is laid over the document when the Panel is
5691
* configured to be modal.
5694
buildMask: function () {
5695
var oMask = this.mask;
5697
if (!m_oMaskTemplate) {
5698
m_oMaskTemplate = document.createElement("div");
5699
m_oMaskTemplate.className = "mask";
5700
m_oMaskTemplate.innerHTML = " ";
5702
oMask = m_oMaskTemplate.cloneNode(true);
5703
oMask.id = this.id + "_mask";
5705
document.body.insertBefore(oMask, document.body.firstChild);
5709
if (YAHOO.env.ua.gecko && this.platform == "mac") {
5710
Dom.addClass(this.mask, "block-scrollbars");
5713
// Stack mask based on the element zindex
5719
* Hides the modality mask.
5722
hideMask: function () {
5723
if (this.cfg.getProperty("modal") && this.mask) {
5724
this.mask.style.display = "none";
5725
this.hideMaskEvent.fire();
5726
Dom.removeClass(document.body, "masked");
5731
* Shows the modality mask.
5734
showMask: function () {
5735
if (this.cfg.getProperty("modal") && this.mask) {
5736
Dom.addClass(document.body, "masked");
5738
this.mask.style.display = "block";
5739
this.showMaskEvent.fire();
5744
* Sets the size of the modality mask to cover the entire scrollable
5745
* area of the document
5748
sizeMask: function () {
5750
this.mask.style.height = Dom.getDocumentHeight() + "px";
5751
this.mask.style.width = Dom.getDocumentWidth() + "px";
5756
* Sets the zindex of the mask, if it exists, based on the zindex of
5757
* the Panel element. The zindex of the mask is set to be one less
5758
* than the Panel element's zindex.
5760
* <p>NOTE: This method will not bump up the zindex of the Panel
5761
* to ensure that the mask has a non-negative zindex. If you require the
5762
* mask zindex to be 0 or higher, the zindex of the Panel
5763
* should be set to a value higher than 0, before this method is called.
5767
stackMask: function() {
5769
var panelZ = Dom.getStyle(this.element, "zIndex");
5770
if (!YAHOO.lang.isUndefined(panelZ) && !isNaN(panelZ)) {
5771
Dom.setStyle(this.mask, "zIndex", panelZ - 1);
5777
* Renders the Panel by inserting the elements that are not already in
5778
* the main Panel into their correct places. Optionally appends the
5779
* Panel to the specified node prior to the render's execution. NOTE:
5780
* For Panels without existing markup, the appendToNode argument is
5781
* REQUIRED. If this argument is ommitted and the current element is
5782
* not present in the document, the function will return false,
5783
* indicating that the render was a failure.
5785
* @param {String} appendToNode The element id to which the Module
5786
* should be appended to prior to rendering <em>OR</em>
5787
* @param {HTMLElement} appendToNode The element to which the Module
5788
* should be appended to prior to rendering
5789
* @return {boolean} Success or failure of the render
5791
render: function (appendToNode) {
5793
return Panel.superclass.render.call(this,
5794
appendToNode, this.innerElement);
5799
* Removes the Panel element from the DOM and sets all child elements
5803
destroy: function () {
5805
Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
5811
Event.purgeElement(this.close);
5815
Panel.superclass.destroy.call(this);
5820
* Returns a String representation of the object.
5822
* @return {String} The string representation of the Panel.
5824
toString: function () {
5825
return "Panel " + this.id;
5836
* Dialog is an implementation of Panel that can be used to submit form
5840
* Built-in functionality for buttons with event handlers is included.
5841
* If the optional YUI Button dependancy is included on the page, the buttons
5842
* created will be instances of YAHOO.widget.Button, otherwise regular HTML buttons
5846
* Forms can be processed in 3 ways -- via an asynchronous Connection utility call,
5847
* a simple form POST or GET, or manually. The YUI Connection utility should be
5848
* included if you're using the default "async" postmethod, but is not required if
5849
* you're using any of the other postmethod values.
5851
* @namespace YAHOO.widget
5853
* @extends YAHOO.widget.Panel
5855
* @param {String} el The element ID representing the Dialog <em>OR</em>
5856
* @param {HTMLElement} el The element representing the Dialog
5857
* @param {Object} userConfig The configuration object literal containing
5858
* the configuration that should be set for this Dialog. See configuration
5859
* documentation for more details.
5861
YAHOO.widget.Dialog = function (el, userConfig) {
5862
YAHOO.widget.Dialog.superclass.constructor.call(this, el, userConfig);
5865
var Event = YAHOO.util.Event,
5866
CustomEvent = YAHOO.util.CustomEvent,
5867
Dom = YAHOO.util.Dom,
5868
KeyListener = YAHOO.util.KeyListener,
5869
Connect = YAHOO.util.Connect,
5870
Dialog = YAHOO.widget.Dialog,
5874
* Constant representing the name of the Dialog's events
5875
* @property EVENT_TYPES
5882
"BEFORE_SUBMIT": "beforeSubmit",
5884
"MANUAL_SUBMIT": "manualSubmit",
5885
"ASYNC_SUBMIT": "asyncSubmit",
5886
"FORM_SUBMIT": "formSubmit",
5892
* Constant representing the Dialog's configuration properties
5893
* @property DEFAULT_CONFIG
5910
"HIDEAFTERSUBMIT" : {
5911
key: "hideaftersubmit",
5917
* Constant representing the default CSS class used for a Dialog
5918
* @property YAHOO.widget.Dialog.CSS_DIALOG
5923
Dialog.CSS_DIALOG = "yui-dialog";
5925
function removeButtonEventHandlers() {
5927
var aButtons = this._aButtons,
5932
if (Lang.isArray(aButtons)) {
5933
nButtons = aButtons.length;
5938
oButton = aButtons[i];
5940
if (YAHOO.widget.Button && oButton instanceof YAHOO.widget.Button) {
5943
else if (oButton.tagName.toUpperCase() == "BUTTON") {
5944
Event.purgeElement(oButton);
5945
Event.purgeElement(oButton, false);
5953
YAHOO.extend(Dialog, YAHOO.widget.Panel, {
5957
* @description Object reference to the Dialog's
5958
* <code><form></code> element.
5960
* @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
5961
* level-one-html.html#ID-40002357">HTMLFormElement</a>
5966
* Initializes the class's configurable properties which can be changed
5967
* using the Dialog's Config object (cfg).
5968
* @method initDefaultConfig
5970
initDefaultConfig: function () {
5971
Dialog.superclass.initDefaultConfig.call(this);
5974
* The internally maintained callback object for use with the
5975
* Connection utility. The format of the callback object is
5976
* similar to Connection Manager's callback object and is
5977
* simply passed through to Connection Manager when the async
5979
* @property callback
5985
* The function to execute upon success of the
5986
* Connection submission (when the form does not
5987
* contain a file input element).
5989
* @property callback.success
5995
* The function to execute upon failure of the
5996
* Connection submission
5997
* @property callback.failure
6004
* The function to execute upon success of the
6005
* Connection submission, when the form contains
6006
* a file input element.
6009
* <em>NOTE:</em> Connection manager will not
6010
* invoke the success or failure handlers for the file
6011
* upload use case. This will be the only callback
6015
* For more information, see the <a href="http://developer.yahoo.com/yui/connection/#file">
6016
* Connection Manager documenation on file uploads</a>.
6018
* @property callback.upload
6023
* The arbitraty argument or arguments to pass to the Connection
6024
* callback functions
6025
* @property callback.argument
6032
// Add form dialog config properties //
6034
* The method to use for posting the Dialog's form. Possible values
6035
* are "async", "form", and "manual".
6036
* @config postmethod
6040
this.cfg.addProperty(DEFAULT_CONFIG.POST_METHOD.key, {
6041
handler: this.configPostMethod,
6042
value: DEFAULT_CONFIG.POST_METHOD.value,
6043
validator: function (val) {
6044
if (val != "form" && val != "async" && val != "none" &&
6054
* This property is used to configure whether or not the
6055
* dialog should be automatically hidden after submit.
6057
* @config hideaftersubmit
6061
this.cfg.addProperty(DEFAULT_CONFIG.HIDEAFTERSUBMIT.key, {
6062
value: DEFAULT_CONFIG.HIDEAFTERSUBMIT.value
6066
* Array of object literals, each containing a set of properties
6067
* defining a button to be appended into the Dialog's footer.
6069
* Each button object in the buttons array can have three properties:
6071
* <dd>The text that will display on the face of the button. The text can
6072
* include HTML, as long as it is compliant with HTML Button specifications.
6075
* <dd>Can be either:
6077
* <li>A reference to a function that should fire when the
6078
* button is clicked. (In this case scope of this function is
6079
* always its Dialog instance.)</li>
6080
* <li>An object literal representing the code to be
6081
* executed when the button is clicked. Format:<br> <code> {<br>
6082
* <strong>fn:</strong> Function, // The handler to call
6083
* when the event fires.<br> <strong>obj:</strong> Object,
6084
* // An object to pass back to the handler.<br> <strong>
6085
* scope:</strong> Object // The object to use for the
6086
* scope of the handler. <br> } </code> <br></li>
6089
* <dt>isDefault:</dt>
6090
* <dd>An optional boolean value that specifies that a button
6091
* should be highlighted and focused by default.</dd>
6093
* <em>NOTE:</em>If the YUI Button Widget is included on the page,
6094
* the buttons created will be instances of YAHOO.widget.Button.
6095
* Otherwise, HTML Buttons (<code><BUTTON></code>) will be
6099
* @type {Array|String}
6102
this.cfg.addProperty(DEFAULT_CONFIG.BUTTONS.key, {
6103
handler: this.configButtons,
6104
value: DEFAULT_CONFIG.BUTTONS.value
6110
* Initializes the custom events for Dialog which are fired
6111
* automatically at appropriate times by the Dialog class.
6112
* @method initEvents
6114
initEvents: function () {
6115
Dialog.superclass.initEvents.call(this);
6117
var SIGNATURE = CustomEvent.LIST;
6120
* CustomEvent fired prior to submission
6121
* @event beforeSubmitEvent
6123
this.beforeSubmitEvent =
6124
this.createEvent(EVENT_TYPES.BEFORE_SUBMIT);
6125
this.beforeSubmitEvent.signature = SIGNATURE;
6128
* CustomEvent fired after submission
6129
* @event submitEvent
6131
this.submitEvent = this.createEvent(EVENT_TYPES.SUBMIT);
6132
this.submitEvent.signature = SIGNATURE;
6135
* CustomEvent fired prior to manual submission
6136
* @event manualSubmitEvent
6138
this.manualSubmitEvent =
6139
this.createEvent(EVENT_TYPES.MANUAL_SUBMIT);
6140
this.manualSubmitEvent.signature = SIGNATURE;
6143
* CustomEvent fired prior to asynchronous submission
6144
* @event asyncSubmitEvent
6146
this.asyncSubmitEvent = this.createEvent(EVENT_TYPES.ASYNC_SUBMIT);
6147
this.asyncSubmitEvent.signature = SIGNATURE;
6150
* CustomEvent fired prior to form-based submission
6151
* @event formSubmitEvent
6153
this.formSubmitEvent = this.createEvent(EVENT_TYPES.FORM_SUBMIT);
6154
this.formSubmitEvent.signature = SIGNATURE;
6157
* CustomEvent fired after cancel
6158
* @event cancelEvent
6160
this.cancelEvent = this.createEvent(EVENT_TYPES.CANCEL);
6161
this.cancelEvent.signature = SIGNATURE;
6166
* The Dialog initialization method, which is executed for Dialog and
6167
* all of its subclasses. This method is automatically called by the
6168
* constructor, and sets up all DOM references for pre-existing markup,
6169
* and creates required markup if it is not already present.
6171
* @param {String} el The element ID representing the Dialog <em>OR</em>
6172
* @param {HTMLElement} el The element representing the Dialog
6173
* @param {Object} userConfig The configuration object literal
6174
* containing the configuration that should be set for this Dialog.
6175
* See configuration documentation for more details.
6177
init: function (el, userConfig) {
6180
Note that we don't pass the user config in here yet because
6181
we only want it executed once, at the lowest subclass level
6184
Dialog.superclass.init.call(this, el/*, userConfig*/);
6186
this.beforeInitEvent.fire(Dialog);
6188
Dom.addClass(this.element, Dialog.CSS_DIALOG);
6190
this.cfg.setProperty("visible", false);
6193
this.cfg.applyConfig(userConfig, true);
6196
this.showEvent.subscribe(this.focusFirst, this, true);
6197
this.beforeHideEvent.subscribe(this.blurButtons, this, true);
6199
this.subscribe("changeBody", this.registerForm);
6201
this.initEvent.fire(Dialog);
6205
* Submits the Dialog's form depending on the value of the
6206
* "postmethod" configuration property. <strong>Please note:
6207
* </strong> As of version 2.3 this method will automatically handle
6208
* asyncronous file uploads should the Dialog instance's form contain
6209
* <code><input type="file"></code> elements. If a Dialog
6210
* instance will be handling asyncronous file uploads, its
6211
* <code>callback</code> property will need to be setup with a
6212
* <code>upload</code> handler rather than the standard
6213
* <code>success</code> and, or <code>failure</code> handlers. For more
6214
* information, see the <a href="http://developer.yahoo.com/yui/
6215
* connection/#file">Connection Manager documenation on file uploads</a>.
6218
doSubmit: function () {
6220
var oForm = this.form,
6221
bUseFileUpload = false,
6222
bUseSecureFileUpload = false,
6228
switch (this.cfg.getProperty("postmethod")) {
6232
aElements = oForm.elements;
6233
nElements = aElements.length;
6235
if (nElements > 0) {
6238
if (aElements[i].type == "file") {
6239
bUseFileUpload = true;
6246
if (bUseFileUpload && YAHOO.env.ua.ie && this.isSecure) {
6247
bUseSecureFileUpload = true;
6250
sMethod = (oForm.getAttribute("method") || "POST").toUpperCase();
6252
Connect.setForm(oForm, bUseFileUpload, bUseSecureFileUpload);
6253
Connect.asyncRequest(sMethod, oForm.getAttribute("action"), this.callback);
6255
this.asyncSubmitEvent.fire();
6262
this.formSubmitEvent.fire();
6269
this.manualSubmitEvent.fire();
6279
* Prepares the Dialog's internal FORM object, creating one if one is
6280
* not currently present.
6281
* @method registerForm
6283
registerForm: function () {
6285
var form = this.element.getElementsByTagName("form")[0],
6292
if (this.form == form &&
6293
Dom.isAncestor(this.element, this.form)) {
6297
Event.purgeElement(this.form);
6303
form = document.createElement("form");
6304
form.name = "frm_" + this.id;
6306
this.body.appendChild(form);
6312
Event.on(form, "submit", function (e) {
6318
this.firstFormElement = function () {
6319
var f, el, nElements = form.elements.length;
6321
for (f = 0; f < nElements; f++) {
6322
el = form.elements[f];
6323
if (el.focus && !el.disabled && el.type != "hidden") {
6330
this.lastFormElement = function () {
6331
var f, el, nElements = form.elements.length;
6333
for (f = nElements - 1; f >= 0; f--) {
6334
el = form.elements[f];
6335
if (el.focus && !el.disabled && el.type != "hidden") {
6342
if (this.cfg.getProperty("modal")) {
6343
firstElement = this.firstFormElement || this.firstButton;
6345
this.preventBackTab = new KeyListener(firstElement,
6346
{ shift: true, keys: 9 },
6347
{ fn: me.focusLast, scope: me,
6348
correctScope: true });
6350
this.showEvent.subscribe(this.preventBackTab.enable,
6351
this.preventBackTab, true);
6353
this.hideEvent.subscribe(this.preventBackTab.disable,
6354
this.preventBackTab, true);
6357
lastElement = this.lastButton || this.lastFormElement;
6360
this.preventTabOut = new KeyListener(lastElement,
6361
{ shift: false, keys: 9 },
6362
{ fn: me.focusFirst, scope: me,
6363
correctScope: true });
6365
this.showEvent.subscribe(this.preventTabOut.enable,
6366
this.preventTabOut, true);
6368
this.hideEvent.subscribe(this.preventTabOut.disable,
6369
this.preventTabOut, true);
6375
// BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
6378
* The default event handler fired when the "close" property is
6379
* changed. The method controls the appending or hiding of the close
6380
* icon at the top right of the Dialog.
6381
* @method configClose
6382
* @param {String} type The CustomEvent type (usually the property name)
6383
* @param {Object[]} args The CustomEvent arguments. For
6384
* configuration handlers, args[0] will equal the newly applied value
6386
* @param {Object} obj The scope object. For configuration handlers,
6387
* this will usually equal the owner.
6389
configClose: function (type, args, obj) {
6392
function doCancel(e, obj) {
6398
this.close = document.createElement("div");
6399
Dom.addClass(this.close, "container-close");
6401
this.close.innerHTML = " ";
6402
this.innerElement.appendChild(this.close);
6403
Event.on(this.close, "click", doCancel, this);
6405
this.close.style.display = "block";
6409
this.close.style.display = "none";
6415
* The default event handler for the "buttons" configuration property
6416
* @method configButtons
6417
* @param {String} type The CustomEvent type (usually the property name)
6418
* @param {Object[]} args The CustomEvent arguments. For configuration
6419
* handlers, args[0] will equal the newly applied value for the property.
6420
* @param {Object} obj The scope object. For configuration handlers,
6421
* this will usually equal the owner.
6423
configButtons: function (type, args, obj) {
6425
var Button = YAHOO.widget.Button,
6427
oInnerElement = this.innerElement,
6436
removeButtonEventHandlers.call(this);
6438
this._aButtons = null;
6440
if (Lang.isArray(aButtons)) {
6442
oSpan = document.createElement("span");
6443
oSpan.className = "button-group";
6445
nButtons = aButtons.length;
6447
this._aButtons = [];
6449
for (i = 0; i < nButtons; i++) {
6451
oButton = aButtons[i];
6455
oYUIButton = new Button({ label: oButton.text,
6456
container: oSpan });
6458
oButtonEl = oYUIButton.get("element");
6460
if (oButton.isDefault) {
6462
oYUIButton.addClass("default");
6464
this.defaultHtmlButton = oButtonEl;
6468
if (Lang.isFunction(oButton.handler)) {
6470
oYUIButton.set("onclick", { fn: oButton.handler,
6471
obj: this, scope: this });
6474
else if (Lang.isObject(oButton.handler) &&
6475
Lang.isFunction(oButton.handler.fn)) {
6477
oYUIButton.set("onclick", { fn: oButton.handler.fn,
6478
obj: ((!Lang.isUndefined(oButton.handler.obj)) ?
6479
oButton.handler.obj : this),
6480
scope: (oButton.handler.scope || this) });
6484
this._aButtons[this._aButtons.length] = oYUIButton;
6489
oButtonEl = document.createElement("button");
6490
oButtonEl.setAttribute("type", "button");
6492
if (oButton.isDefault) {
6493
oButtonEl.className = "default";
6494
this.defaultHtmlButton = oButtonEl;
6497
oButtonEl.innerHTML = oButton.text;
6499
if (Lang.isFunction(oButton.handler)) {
6501
Event.on(oButtonEl, "click", oButton.handler,
6505
else if (Lang.isObject(oButton.handler) &&
6506
Lang.isFunction(oButton.handler.fn)) {
6508
Event.on(oButtonEl, "click", oButton.handler.fn,
6509
((!Lang.isUndefined(oButton.handler.obj)) ?
6510
oButton.handler.obj : this),
6511
(oButton.handler.scope || this));
6515
oSpan.appendChild(oButtonEl);
6517
this._aButtons[this._aButtons.length] = oButtonEl;
6521
oButton.htmlButton = oButtonEl;
6524
this.firstButton = oButtonEl;
6527
if (i == (nButtons - 1)) {
6528
this.lastButton = oButtonEl;
6533
this.setFooter(oSpan);
6535
oFooter = this.footer;
6537
if (Dom.inDocument(this.element) &&
6538
!Dom.isAncestor(oInnerElement, oFooter)) {
6540
oInnerElement.appendChild(oFooter);
6544
this.buttonSpan = oSpan;
6546
} else { // Do cleanup
6548
oSpan = this.buttonSpan;
6549
oFooter = this.footer;
6551
if (oSpan && oFooter) {
6553
oFooter.removeChild(oSpan);
6555
this.buttonSpan = null;
6556
this.firstButton = null;
6557
this.lastButton = null;
6558
this.defaultHtmlButton = null;
6564
this.cfg.refireEvent("iframe");
6565
this.cfg.refireEvent("underlay");
6569
* @method getButtons
6570
* @description Returns an array containing each of the Dialog's
6571
* buttons, by default an array of HTML <code><BUTTON></code>
6572
* elements. If the Dialog's buttons were created using the
6573
* YAHOO.widget.Button class (via the inclusion of the optional Button
6574
* dependancy on the page), an array of YAHOO.widget.Button instances
6578
getButtons: function () {
6579
var aButtons = this._aButtons;
6586
* Sets focus to the first element in the Dialog's form or the first
6587
* button defined via the "buttons" configuration property. Called
6588
* when the Dialog is made visible.
6589
* @method focusFirst
6591
focusFirst: function (type, args, obj) {
6593
var oElement = this.firstFormElement,
6599
Event.stopEvent(oEvent);
6605
Place the call to the "focus" method inside a try/catch
6606
block to prevent IE from throwing JavaScript errors if
6607
the element is disabled or hidden.
6616
this.focusDefaultButton();
6621
* Sets focus to the last element in the Dialog's form or the last
6622
* button defined via the "buttons" configuration property.
6625
focusLast: function (type, args, obj) {
6627
var aButtons = this.cfg.getProperty("buttons"),
6628
oElement = this.lastFormElement,
6634
Event.stopEvent(oEvent);
6638
if (aButtons && Lang.isArray(aButtons)) {
6639
this.focusLastButton();
6643
Place the call to the "focus" method inside a try/catch
6644
block to prevent IE from throwing JavaScript errors if
6645
the element is disabled or hidden.
6650
} catch(oException) {
6657
* Sets the focus to the button that is designated as the default via
6658
* the "buttons" configuration property. By default, this method is
6659
* called when the Dialog is made visible.
6660
* @method focusDefaultButton
6662
focusDefaultButton: function () {
6664
var oElement = this.defaultHtmlButton;
6669
Place the call to the "focus" method inside a try/catch
6670
block to prevent IE from throwing JavaScript errors if
6671
the element is disabled or hidden.
6675
} catch(oException) {
6682
* Blurs all the buttons defined via the "buttons"
6683
* configuration property.
6684
* @method blurButtons
6686
blurButtons: function () {
6688
var aButtons = this.cfg.getProperty("buttons"),
6694
if (aButtons && Lang.isArray(aButtons)) {
6696
nButtons = aButtons.length;
6703
oButton = aButtons[i];
6707
oElement = oButton.htmlButton;
6711
Place the call to the "blur" method inside
6712
a try/catch block to prevent IE from
6713
throwing JavaScript errors if the element
6714
is disabled or hidden.
6718
} catch(oException) {
6729
* Sets the focus to the first button created via the "buttons"
6730
* configuration property.
6731
* @method focusFirstButton
6733
focusFirstButton: function () {
6735
var aButtons = this.cfg.getProperty("buttons"),
6739
if (aButtons && Lang.isArray(aButtons)) {
6741
oButton = aButtons[0];
6745
oElement = oButton.htmlButton;
6750
Place the call to the "focus" method inside a
6751
try/catch block to prevent IE from throwing
6752
JavaScript errors if the element is disabled
6767
* Sets the focus to the last button created via the "buttons"
6768
* configuration property.
6769
* @method focusLastButton
6771
focusLastButton: function () {
6773
var aButtons = this.cfg.getProperty("buttons"),
6778
if (aButtons && Lang.isArray(aButtons)) {
6780
nButtons = aButtons.length;
6783
oButton = aButtons[(nButtons - 1)];
6786
oElement = oButton.htmlButton;
6789
Place the call to the "focus" method inside a
6790
try/catch block to prevent IE from throwing
6791
JavaScript errors if the element is disabled
6797
} catch(oException) {
6806
* The default event handler for the "postmethod" configuration property
6807
* @method configPostMethod
6808
* @param {String} type The CustomEvent type (usually the property name)
6809
* @param {Object[]} args The CustomEvent arguments. For
6810
* configuration handlers, args[0] will equal the newly applied value
6812
* @param {Object} obj The scope object. For configuration handlers,
6813
* this will usually equal the owner.
6815
configPostMethod: function (type, args, obj) {
6816
this.registerForm();
6819
// END BUILT-IN PROPERTY EVENT HANDLERS //
6822
* Built-in function hook for writing a validation function that will
6823
* be checked for a "true" value prior to a submit. This function, as
6824
* implemented by default, always returns true, so it should be
6825
* overridden if validation is necessary.
6828
validate: function () {
6833
* Executes a submit of the Dialog if validation
6834
* is successful. By default the Dialog is hidden
6835
* after submission, but you can set the "hideaftersubmit"
6836
* configuration property to false, to prevent the Dialog
6837
* from being hidden.
6841
submit: function () {
6842
if (this.validate()) {
6843
this.beforeSubmitEvent.fire();
6845
this.submitEvent.fire();
6847
if (this.cfg.getProperty("hideaftersubmit")) {
6858
* Executes the cancel of the Dialog followed by a hide.
6861
cancel: function () {
6862
this.cancelEvent.fire();
6867
* Returns a JSON-compatible data structure representing the data
6868
* currently contained in the form.
6870
* @return {Object} A JSON object reprsenting the data of the
6873
getData: function () {
6875
var oForm = this.form,
6894
function isFormElement(p_oElement) {
6896
var sTag = p_oElement.tagName.toUpperCase();
6898
return ((sTag == "INPUT" || sTag == "TEXTAREA" ||
6899
sTag == "SELECT") && p_oElement.name == sName);
6906
aElements = oForm.elements;
6907
nTotalElements = aElements.length;
6911
for (i = 0; i < nTotalElements; i++) {
6913
sName = aElements[i].name;
6916
Using "Dom.getElementsBy" to safeguard user from JS
6917
errors that result from giving a form field (or set of
6918
fields) the same name as a native method of a form
6919
(like "submit") or a DOM collection (such as the "item"
6920
method). Originally tried accessing fields via the
6921
"namedItem" method of the "element" collection, but
6922
discovered that it won't return a collection of fields
6926
oElement = Dom.getElementsBy(isFormElement, "*", oForm);
6927
nElements = oElement.length;
6929
if (nElements > 0) {
6931
if (nElements == 1) {
6933
oElement = oElement[0];
6935
sType = oElement.type;
6936
sTagName = oElement.tagName.toUpperCase();
6942
if (sType == "checkbox") {
6944
oData[sName] = oElement.checked;
6947
else if (sType != "radio") {
6949
oData[sName] = oElement.value;
6957
oData[sName] = oElement.value;
6963
aOptions = oElement.options;
6964
nOptions = aOptions.length;
6967
for (n = 0; n < nOptions; n++) {
6969
oOption = aOptions[n];
6971
if (oOption.selected) {
6973
sValue = oOption.value;
6975
if (!sValue || sValue === "") {
6977
sValue = oOption.text;
6981
aValues[aValues.length] = sValue;
6987
oData[sName] = aValues;
6997
sType = oElement[0].type;
7003
for (n = 0; n < nElements; n++) {
7005
oRadio = oElement[n];
7007
if (oRadio.checked) {
7009
oData[sName] = oRadio.value;
7022
for (n = 0; n < nElements; n++) {
7024
oCheckbox = oElement[n];
7026
if (oCheckbox.checked) {
7028
aValues[aValues.length] =
7035
oData[sName] = aValues;
7055
* Removes the Panel element from the DOM and sets all child elements
7059
destroy: function () {
7061
removeButtonEventHandlers.call(this);
7063
this._aButtons = null;
7065
var aForms = this.element.getElementsByTagName("form"),
7068
if (aForms.length > 0) {
7073
Event.purgeElement(oForm);
7074
if (oForm.parentNode) {
7075
oForm.parentNode.removeChild(oForm);
7081
Dialog.superclass.destroy.call(this);
7086
* Returns a string representation of the object.
7088
* @return {String} The string representation of the Dialog
7090
toString: function () {
7091
return "Dialog " + this.id;
7101
* SimpleDialog is a simple implementation of Dialog that can be used to
7102
* submit a single value. Forms can be processed in 3 ways -- via an
7103
* asynchronous Connection utility call, a simple form POST or GET,
7105
* @namespace YAHOO.widget
7106
* @class SimpleDialog
7107
* @extends YAHOO.widget.Dialog
7109
* @param {String} el The element ID representing the SimpleDialog
7111
* @param {HTMLElement} el The element representing the SimpleDialog
7112
* @param {Object} userConfig The configuration object literal containing
7113
* the configuration that should be set for this SimpleDialog. See
7114
* configuration documentation for more details.
7116
YAHOO.widget.SimpleDialog = function (el, userConfig) {
7118
YAHOO.widget.SimpleDialog.superclass.constructor.call(this,
7123
var Dom = YAHOO.util.Dom,
7124
SimpleDialog = YAHOO.widget.SimpleDialog,
7127
* Constant representing the SimpleDialog's configuration properties
7128
* @property DEFAULT_CONFIG
7144
suppressEvent: true,
7145
supercedes: ["icon"]
7151
* Constant for the standard network icon for a blocking action
7152
* @property YAHOO.widget.SimpleDialog.ICON_BLOCK
7157
SimpleDialog.ICON_BLOCK = "blckicon";
7160
* Constant for the standard network icon for alarm
7161
* @property YAHOO.widget.SimpleDialog.ICON_ALARM
7166
SimpleDialog.ICON_ALARM = "alrticon";
7169
* Constant for the standard network icon for help
7170
* @property YAHOO.widget.SimpleDialog.ICON_HELP
7175
SimpleDialog.ICON_HELP = "hlpicon";
7178
* Constant for the standard network icon for info
7179
* @property YAHOO.widget.SimpleDialog.ICON_INFO
7184
SimpleDialog.ICON_INFO = "infoicon";
7187
* Constant for the standard network icon for warn
7188
* @property YAHOO.widget.SimpleDialog.ICON_WARN
7193
SimpleDialog.ICON_WARN = "warnicon";
7196
* Constant for the standard network icon for a tip
7197
* @property YAHOO.widget.SimpleDialog.ICON_TIP
7202
SimpleDialog.ICON_TIP = "tipicon";
7205
* Constant representing the name of the CSS class applied to the element
7206
* created by the "icon" configuration property.
7207
* @property YAHOO.widget.SimpleDialog.ICON_CSS_CLASSNAME
7212
SimpleDialog.ICON_CSS_CLASSNAME = "yui-icon";
7215
* Constant representing the default CSS class used for a SimpleDialog
7216
* @property YAHOO.widget.SimpleDialog.CSS_SIMPLEDIALOG
7221
SimpleDialog.CSS_SIMPLEDIALOG = "yui-simple-dialog";
7224
YAHOO.extend(SimpleDialog, YAHOO.widget.Dialog, {
7227
* Initializes the class's configurable properties which can be changed
7228
* using the SimpleDialog's Config object (cfg).
7229
* @method initDefaultConfig
7231
initDefaultConfig: function () {
7233
SimpleDialog.superclass.initDefaultConfig.call(this);
7235
// Add dialog config properties //
7238
* Sets the informational icon for the SimpleDialog
7243
this.cfg.addProperty(DEFAULT_CONFIG.ICON.key, {
7244
handler: this.configIcon,
7245
value: DEFAULT_CONFIG.ICON.value,
7246
suppressEvent: DEFAULT_CONFIG.ICON.suppressEvent
7250
* Sets the text for the SimpleDialog
7255
this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, {
7256
handler: this.configText,
7257
value: DEFAULT_CONFIG.TEXT.value,
7258
suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent,
7259
supercedes: DEFAULT_CONFIG.TEXT.supercedes
7266
* The SimpleDialog initialization method, which is executed for
7267
* SimpleDialog and all of its subclasses. This method is automatically
7268
* called by the constructor, and sets up all DOM references for
7269
* pre-existing markup, and creates required markup if it is not
7272
* @param {String} el The element ID representing the SimpleDialog
7274
* @param {HTMLElement} el The element representing the SimpleDialog
7275
* @param {Object} userConfig The configuration object literal
7276
* containing the configuration that should be set for this
7277
* SimpleDialog. See configuration documentation for more details.
7279
init: function (el, userConfig) {
7282
Note that we don't pass the user config in here yet because we
7283
only want it executed once, at the lowest subclass level
7286
SimpleDialog.superclass.init.call(this, el/*, userConfig*/);
7288
this.beforeInitEvent.fire(SimpleDialog);
7290
Dom.addClass(this.element, SimpleDialog.CSS_SIMPLEDIALOG);
7292
this.cfg.queueProperty("postmethod", "manual");
7295
this.cfg.applyConfig(userConfig, true);
7298
this.beforeRenderEvent.subscribe(function () {
7304
this.initEvent.fire(SimpleDialog);
7309
* Prepares the SimpleDialog's internal FORM object, creating one if one
7310
* is not currently present, and adding the value hidden field.
7311
* @method registerForm
7313
registerForm: function () {
7315
SimpleDialog.superclass.registerForm.call(this);
7317
this.form.innerHTML += "<input type=\"hidden\" name=\"" +
7318
this.id + "\" value=\"\"/>";
7322
// BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
7325
* Fired when the "icon" property is set.
7326
* @method configIcon
7327
* @param {String} type The CustomEvent type (usually the property name)
7328
* @param {Object[]} args The CustomEvent arguments. For configuration
7329
* handlers, args[0] will equal the newly applied value for the property.
7330
* @param {Object} obj The scope object. For configuration handlers,
7331
* this will usually equal the owner.
7333
configIcon: function (type,args,obj) {
7335
var sIcon = args[0],
7337
sCSSClass = SimpleDialog.ICON_CSS_CLASSNAME,
7341
if (sIcon && sIcon != "none") {
7343
oIcon = Dom.getElementsByClassName(sCSSClass, "*" , oBody);
7347
oIconParent = oIcon.parentNode;
7351
oIconParent.removeChild(oIcon);
7360
if (sIcon.indexOf(".") == -1) {
7362
oIcon = document.createElement("span");
7363
oIcon.className = (sCSSClass + " " + sIcon);
7364
oIcon.innerHTML = " ";
7368
oIcon = document.createElement("img");
7369
oIcon.src = (this.imageRoot + sIcon);
7370
oIcon.className = sCSSClass;
7377
oBody.insertBefore(oIcon, oBody.firstChild);
7386
* Fired when the "text" property is set.
7387
* @method configText
7388
* @param {String} type The CustomEvent type (usually the property name)
7389
* @param {Object[]} args The CustomEvent arguments. For configuration
7390
* handlers, args[0] will equal the newly applied value for the property.
7391
* @param {Object} obj The scope object. For configuration handlers,
7392
* this will usually equal the owner.
7394
configText: function (type,args,obj) {
7398
this.cfg.refireEvent("icon");
7402
// END BUILT-IN PROPERTY EVENT HANDLERS //
7405
* Returns a string representation of the object.
7407
* @return {String} The string representation of the SimpleDialog
7409
toString: function () {
7410
return "SimpleDialog " + this.id;
7420
* ContainerEffect encapsulates animation transitions that are executed when
7421
* an Overlay is shown or hidden.
7422
* @namespace YAHOO.widget
7423
* @class ContainerEffect
7425
* @param {YAHOO.widget.Overlay} overlay The Overlay that the animation
7426
* should be associated with
7427
* @param {Object} attrIn The object literal representing the animation
7428
* arguments to be used for the animate-in transition. The arguments for
7429
* this literal are: attributes(object, see YAHOO.util.Anim for description),
7430
* duration(Number), and method(i.e. Easing.easeIn).
7431
* @param {Object} attrOut The object literal representing the animation
7432
* arguments to be used for the animate-out transition. The arguments for
7433
* this literal are: attributes(object, see YAHOO.util.Anim for description),
7434
* duration(Number), and method(i.e. Easing.easeIn).
7435
* @param {HTMLElement} targetElement Optional. The target element that
7436
* should be animated during the transition. Defaults to overlay.element.
7437
* @param {class} Optional. The animation class to instantiate. Defaults to
7438
* YAHOO.util.Anim. Other options include YAHOO.util.Motion.
7440
YAHOO.widget.ContainerEffect =
7442
function (overlay, attrIn, attrOut, targetElement, animClass) {
7445
animClass = YAHOO.util.Anim;
7449
* The overlay to animate
7451
* @type YAHOO.widget.Overlay
7453
this.overlay = overlay;
7456
* The animation attributes to use when transitioning into view
7460
this.attrIn = attrIn;
7463
* The animation attributes to use when transitioning out of view
7467
this.attrOut = attrOut;
7470
* The target element to be animated
7471
* @property targetElement
7474
this.targetElement = targetElement || overlay.element;
7477
* The animation class to use for animating the overlay
7478
* @property animClass
7481
this.animClass = animClass;
7486
var Dom = YAHOO.util.Dom,
7487
CustomEvent = YAHOO.util.CustomEvent,
7488
Easing = YAHOO.util.Easing,
7489
ContainerEffect = YAHOO.widget.ContainerEffect;
7493
* A pre-configured ContainerEffect instance that can be used for fading
7494
* an overlay in and out.
7497
* @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
7498
* @param {Number} dur The duration of the animation
7499
* @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
7501
ContainerEffect.FADE = function (overlay, dur) {
7504
attributes: {opacity:{from:0, to:1}},
7506
method: Easing.easeIn
7510
attributes: {opacity:{to:0}},
7512
method: Easing.easeOut
7515
var fade = new ContainerEffect(overlay, fin, fout, overlay.element);
7517
fade.handleUnderlayStart = function() {
7518
var underlay = this.overlay.underlay;
7519
if (underlay && YAHOO.env.ua.ie) {
7520
var hasFilters = (underlay.filters && underlay.filters.length > 0);
7522
Dom.addClass(overlay.element, "yui-effect-fade");
7527
fade.handleUnderlayComplete = function() {
7528
var underlay = this.overlay.underlay;
7529
if (underlay && YAHOO.env.ua.ie) {
7530
Dom.removeClass(overlay.element, "yui-effect-fade");
7534
fade.handleStartAnimateIn = function (type,args,obj) {
7535
Dom.addClass(obj.overlay.element, "hide-select");
7537
if (!obj.overlay.underlay) {
7538
obj.overlay.cfg.refireEvent("underlay");
7541
obj.handleUnderlayStart();
7543
Dom.setStyle(obj.overlay.element, "visibility", "visible");
7544
Dom.setStyle(obj.overlay.element, "opacity", 0);
7547
fade.handleCompleteAnimateIn = function (type,args,obj) {
7548
Dom.removeClass(obj.overlay.element, "hide-select");
7550
if (obj.overlay.element.style.filter) {
7551
obj.overlay.element.style.filter = null;
7554
obj.handleUnderlayComplete();
7556
obj.overlay.cfg.refireEvent("iframe");
7557
obj.animateInCompleteEvent.fire();
7560
fade.handleStartAnimateOut = function (type, args, obj) {
7561
Dom.addClass(obj.overlay.element, "hide-select");
7562
obj.handleUnderlayStart();
7565
fade.handleCompleteAnimateOut = function (type, args, obj) {
7566
Dom.removeClass(obj.overlay.element, "hide-select");
7567
if (obj.overlay.element.style.filter) {
7568
obj.overlay.element.style.filter = null;
7570
Dom.setStyle(obj.overlay.element, "visibility", "hidden");
7571
Dom.setStyle(obj.overlay.element, "opacity", 1);
7573
obj.handleUnderlayComplete();
7575
obj.overlay.cfg.refireEvent("iframe");
7576
obj.animateOutCompleteEvent.fire();
7585
* A pre-configured ContainerEffect instance that can be used for sliding an
7586
* overlay in and out.
7589
* @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
7590
* @param {Number} dur The duration of the animation
7591
* @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
7593
ContainerEffect.SLIDE = function (overlay, dur) {
7595
var x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
7597
y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
7599
clientWidth = Dom.getClientWidth(),
7601
offsetWidth = overlay.element.offsetWidth,
7603
slide = new ContainerEffect(overlay,
7605
{ attributes: { points: { to: [x, y] } },
7607
method: Easing.easeIn },
7609
{ attributes: { points: { to: [(clientWidth + 25), y] } },
7611
method: Easing.easeOut },
7613
overlay.element, YAHOO.util.Motion);
7616
slide.handleStartAnimateIn = function (type,args,obj) {
7617
obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
7618
obj.overlay.element.style.top = y + "px";
7621
slide.handleTweenAnimateIn = function (type, args, obj) {
7623
var pos = Dom.getXY(obj.overlay.element),
7627
if (Dom.getStyle(obj.overlay.element, "visibility") ==
7628
"hidden" && currentX < x) {
7630
Dom.setStyle(obj.overlay.element, "visibility", "visible");
7634
obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
7635
obj.overlay.cfg.refireEvent("iframe");
7638
slide.handleCompleteAnimateIn = function (type, args, obj) {
7639
obj.overlay.cfg.setProperty("xy", [x, y], true);
7642
obj.overlay.cfg.refireEvent("iframe");
7643
obj.animateInCompleteEvent.fire();
7646
slide.handleStartAnimateOut = function (type, args, obj) {
7648
var vw = Dom.getViewportWidth(),
7649
pos = Dom.getXY(obj.overlay.element),
7652
obj.animOut.attributes.points.to = [(vw + 25), yso];
7655
slide.handleTweenAnimateOut = function (type, args, obj) {
7657
var pos = Dom.getXY(obj.overlay.element),
7661
obj.overlay.cfg.setProperty("xy", [xto, yto], true);
7662
obj.overlay.cfg.refireEvent("iframe");
7665
slide.handleCompleteAnimateOut = function (type, args, obj) {
7666
Dom.setStyle(obj.overlay.element, "visibility", "hidden");
7668
obj.overlay.cfg.setProperty("xy", [x, y]);
7669
obj.animateOutCompleteEvent.fire();
7676
ContainerEffect.prototype = {
7679
* Initializes the animation classes and events.
7684
this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
7685
this.beforeAnimateInEvent.signature = CustomEvent.LIST;
7687
this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
7688
this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
7690
this.animateInCompleteEvent = this.createEvent("animateInComplete");
7691
this.animateInCompleteEvent.signature = CustomEvent.LIST;
7693
this.animateOutCompleteEvent =
7694
this.createEvent("animateOutComplete");
7695
this.animateOutCompleteEvent.signature = CustomEvent.LIST;
7697
this.animIn = new this.animClass(this.targetElement,
7698
this.attrIn.attributes, this.attrIn.duration,
7699
this.attrIn.method);
7701
this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
7702
this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
7704
this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn,
7707
this.animOut = new this.animClass(this.targetElement,
7708
this.attrOut.attributes, this.attrOut.duration,
7709
this.attrOut.method);
7711
this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
7712
this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
7713
this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut,
7719
* Triggers the in-animation.
7722
animateIn: function () {
7723
this.beforeAnimateInEvent.fire();
7724
this.animIn.animate();
7728
* Triggers the out-animation.
7729
* @method animateOut
7731
animateOut: function () {
7732
this.beforeAnimateOutEvent.fire();
7733
this.animOut.animate();
7737
* The default onStart handler for the in-animation.
7738
* @method handleStartAnimateIn
7739
* @param {String} type The CustomEvent type
7740
* @param {Object[]} args The CustomEvent arguments
7741
* @param {Object} obj The scope object
7743
handleStartAnimateIn: function (type, args, obj) { },
7746
* The default onTween handler for the in-animation.
7747
* @method handleTweenAnimateIn
7748
* @param {String} type The CustomEvent type
7749
* @param {Object[]} args The CustomEvent arguments
7750
* @param {Object} obj The scope object
7752
handleTweenAnimateIn: function (type, args, obj) { },
7755
* The default onComplete handler for the in-animation.
7756
* @method handleCompleteAnimateIn
7757
* @param {String} type The CustomEvent type
7758
* @param {Object[]} args The CustomEvent arguments
7759
* @param {Object} obj The scope object
7761
handleCompleteAnimateIn: function (type, args, obj) { },
7764
* The default onStart handler for the out-animation.
7765
* @method handleStartAnimateOut
7766
* @param {String} type The CustomEvent type
7767
* @param {Object[]} args The CustomEvent arguments
7768
* @param {Object} obj The scope object
7770
handleStartAnimateOut: function (type, args, obj) { },
7773
* The default onTween handler for the out-animation.
7774
* @method handleTweenAnimateOut
7775
* @param {String} type The CustomEvent type
7776
* @param {Object[]} args The CustomEvent arguments
7777
* @param {Object} obj The scope object
7779
handleTweenAnimateOut: function (type, args, obj) { },
7782
* The default onComplete handler for the out-animation.
7783
* @method handleCompleteAnimateOut
7784
* @param {String} type The CustomEvent type
7785
* @param {Object[]} args The CustomEvent arguments
7786
* @param {Object} obj The scope object
7788
handleCompleteAnimateOut: function (type, args, obj) { },
7791
* Returns a string representation of the object.
7793
* @return {String} The string representation of the ContainerEffect
7795
toString: function () {
7796
var output = "ContainerEffect";
7798
output += " [" + this.overlay.toString() + "]";
7805
YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
7809
YAHOO.register("container", YAHOO.widget.Module, {version: "2.5.0", build: "895"});