~ubuntu-branches/ubuntu/jaunty/moodle/jaunty

« back to all changes in this revision

Viewing changes to lib/yui/container/container_core-debug.js

  • Committer: Bazaar Package Importer
  • Author(s): Jordan Mantha, Matt Oquist
  • Date: 2009-02-25 15:16:22 UTC
  • mfrom: (1.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20090225151622-0ekt1liwhv2obfza
Tags: 1.9.4.dfsg-0ubuntu1
* Merge with Debian git (Closes LP: #322961, #239481, #334611):
  - use Ubuntu's smarty lib directory for linking
  - use internal yui library 
  - add update-notifier support back in

[Matt Oquist]
  * renamed prerm script
  * significantly rewrote postinst and other maintainer scripts to improve
    user experience and package maintainability
    (Closes LP: #225662, #325450, #327843, #303078, #234609)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
 
2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3
3
Code licensed under the BSD License:
4
4
http://developer.yahoo.net/yui/license.txt
5
 
version: 0.12.2
6
 
*/
7
 
/**
8
 
* Config is a utility used within an Object to allow the implementer to maintain a list of local configuration properties and listen for changes to those properties dynamically using CustomEvent. The initial values are also maintained so that the configuration can be reset at any given point to its initial state.
9
 
* @namespace YAHOO.util
10
 
* @class Config
11
 
* @constructor
12
 
* @param {Object}       owner   The owner Object to which this Config Object belongs
13
 
*/
14
 
YAHOO.util.Config = function(owner) {
15
 
        if (owner) {
16
 
                this.init(owner);
17
 
        } else {
18
 
                YAHOO.log("No owner specified for Config object", "error");
19
 
        }
20
 
};
21
 
 
22
 
YAHOO.util.Config.prototype = {
23
 
        
24
 
        /**
25
 
        * Object reference to the owner of this Config Object
26
 
        * @property owner
27
 
        * @type Object
28
 
        */
29
 
        owner : null,
30
 
 
31
 
        /**
32
 
        * Boolean flag that specifies whether a queue is currently being executed
33
 
        * @property queueInProgress
34
 
        * @type Boolean
35
 
        */
36
 
        queueInProgress : false,
37
 
 
38
 
 
39
 
        /**
40
 
        * Validates that the value passed in is a Boolean.
41
 
        * @method checkBoolean
42
 
        * @param        {Object}        val     The value to validate
43
 
        * @return       {Boolean}       true, if the value is valid
44
 
        */      
45
 
        checkBoolean: function(val) {
46
 
                if (typeof val == 'boolean') {
47
 
                        return true;
48
 
                } else {
49
 
                        return false;
50
 
                }
51
 
        },
52
 
 
53
 
        /**
54
 
        * Validates that the value passed in is a number.
55
 
        * @method checkNumber
56
 
        * @param        {Object}        val     The value to validate
57
 
        * @return       {Boolean}       true, if the value is valid
58
 
        */
59
 
        checkNumber: function(val) {
60
 
                if (isNaN(val)) {
61
 
                        return false;
62
 
                } else {
63
 
                        return true;
64
 
                }
65
 
        }
66
 
};
67
 
 
68
 
 
69
 
/**
70
 
* Initializes the configuration Object and all of its local members.
71
 
* @method init
72
 
* @param {Object}       owner   The owner Object to which this Config Object belongs
73
 
*/
74
 
YAHOO.util.Config.prototype.init = function(owner) {
75
 
 
76
 
        this.owner = owner;
77
 
 
78
 
        /**
79
 
        * Object reference to the owner of this Config Object
80
 
        * @event configChangedEvent
81
 
        */
82
 
        this.configChangedEvent = new YAHOO.util.CustomEvent("configChanged");
83
 
        this.queueInProgress = false;
84
 
 
85
 
        /* Private Members */
86
 
 
87
 
        /**
88
 
        * Maintains the local collection of configuration property objects and their specified values
89
 
        * @property config
90
 
        * @private
91
 
        * @type Object
92
 
        */ 
93
 
        var config = {};
94
 
 
95
 
        /**
96
 
        * Maintains the local collection of configuration property objects as they were initially applied.
97
 
        * This object is used when resetting a property.
98
 
        * @property initialConfig
99
 
        * @private
100
 
        * @type Object
101
 
        */ 
102
 
        var initialConfig = {};
103
 
 
104
 
        /**
105
 
        * Maintains the local, normalized CustomEvent queue
106
 
        * @property eventQueue
107
 
        * @private
108
 
        * @type Object
109
 
        */ 
110
 
        var eventQueue = [];
111
 
 
112
 
        /**
113
 
        * Fires a configuration property event using the specified value. 
114
 
        * @method fireEvent
115
 
        * @private
116
 
        * @param {String}       key                     The configuration property's name
117
 
        * @param {value}        Object          The value of the correct type for the property
118
 
        */ 
119
 
        var fireEvent = function( key, value ) {
120
 
                YAHOO.log("Firing Config event: " + key + "=" + value, "info");
121
 
                
122
 
                key = key.toLowerCase();
123
 
 
124
 
                var property = config[key];
125
 
 
126
 
                if (typeof property != 'undefined' && property.event) {
127
 
                        property.event.fire(value);
128
 
                }       
129
 
        };
130
 
        /* End Private Members */
131
 
 
132
 
        /**
133
 
        * Adds a property to the Config Object's private config hash.
134
 
        * @method addProperty
135
 
        * @param {String}       key     The configuration property's name
136
 
        * @param {Object}       propertyObject  The Object containing all of this property's arguments
137
 
        */
138
 
        this.addProperty = function( key, propertyObject ) {
139
 
                key = key.toLowerCase();
140
 
                
141
 
                YAHOO.log("Added property: " + key, "info");
142
 
 
143
 
                config[key] = propertyObject;
144
 
 
145
 
                propertyObject.event = new YAHOO.util.CustomEvent(key);
146
 
                propertyObject.key = key;
147
 
 
148
 
                if (propertyObject.handler) {
149
 
                        propertyObject.event.subscribe(propertyObject.handler, this.owner, true);
150
 
                }
151
 
 
152
 
                this.setProperty(key, propertyObject.value, true);
153
 
                
154
 
                if (! propertyObject.suppressEvent) {
155
 
                        this.queueProperty(key, propertyObject.value);
156
 
                }
157
 
        };
158
 
 
159
 
        /**
160
 
        * Returns a key-value configuration map of the values currently set in the Config Object.
161
 
        * @method getConfig
162
 
        * @return {Object} The current config, represented in a key-value map
163
 
        */
164
 
        this.getConfig = function() {
165
 
                var cfg = {};
166
 
                        
167
 
                for (var prop in config) {
168
 
                        var property = config[prop];
169
 
                        if (typeof property != 'undefined' && property.event) {
170
 
                                cfg[prop] = property.value;
171
 
                        }
172
 
                }
173
 
                
174
 
                return cfg;
175
 
        };
176
 
 
177
 
        /**
178
 
        * Returns the value of specified property.
179
 
        * @method getProperty
180
 
        * @param {String} key   The name of the property
181
 
        * @return {Object}              The value of the specified property
182
 
        */
183
 
        this.getProperty = function(key) {
184
 
                key = key.toLowerCase();
185
 
 
186
 
                var property = config[key];
187
 
                if (typeof property != 'undefined' && property.event) {
188
 
                        return property.value;
189
 
                } else {
190
 
                        return undefined;
191
 
                }
192
 
        };
193
 
 
194
 
        /**
195
 
        * Resets the specified property's value to its initial value.
196
 
        * @method resetProperty
197
 
        * @param {String} key   The name of the property
198
 
        * @return {Boolean} True is the property was reset, false if not
199
 
        */
200
 
        this.resetProperty = function(key) {
201
 
                key = key.toLowerCase();
202
 
 
203
 
                var property = config[key];
204
 
                if (typeof property != 'undefined' && property.event) {
205
 
                        if (initialConfig[key] && initialConfig[key] != 'undefined')    {
206
 
                                this.setProperty(key, initialConfig[key]);
207
 
                        }
208
 
                        return true;
209
 
                } else {
210
 
                        return false;
211
 
                }
212
 
        };
213
 
 
214
 
        /**
215
 
        * Sets the value of a property. If the silent property is passed as true, the property's event will not be fired.
216
 
        * @method setProperty
217
 
        * @param {String} key           The name of the property
218
 
        * @param {String} value         The value to set the property to
219
 
        * @param {Boolean} silent       Whether the value should be set silently, without firing the property event.
220
 
        * @return {Boolean}                     True, if the set was successful, false if it failed.
221
 
        */
222
 
        this.setProperty = function(key, value, silent) {
223
 
                key = key.toLowerCase();
224
 
                
225
 
                YAHOO.log("setProperty: " + key + "=" + value, "info");
226
 
 
227
 
                if (this.queueInProgress && ! silent) {
228
 
                        this.queueProperty(key,value); // Currently running through a queue... 
229
 
                        return true;
230
 
                } else {
231
 
                        var property = config[key];
232
 
                        if (typeof property != 'undefined' && property.event) {
233
 
                                if (property.validator && ! property.validator(value)) { // validator
234
 
                                        return false;
235
 
                                } else {
236
 
                                        property.value = value;
237
 
                                        if (! silent) {
238
 
                                                fireEvent(key, value);
239
 
                                                this.configChangedEvent.fire([key, value]);
240
 
                                        }
241
 
                                        return true;
242
 
                                }
243
 
                        } else {
244
 
                                return false;
245
 
                        }
246
 
                }
247
 
        };
248
 
 
249
 
        /**
250
 
        * Sets the value of a property and queues its event to execute. If the event is already scheduled to execute, it is
251
 
        * moved from its current position to the end of the queue.
252
 
        * @method queueProperty
253
 
        * @param {String} key   The name of the property
254
 
        * @param {String} value The value to set the property to
255
 
        * @return {Boolean}             true, if the set was successful, false if it failed.
256
 
        */      
257
 
        this.queueProperty = function(key, value) {
258
 
                key = key.toLowerCase();
259
 
 
260
 
                YAHOO.log("queueProperty: " + key + "=" + value, "info");
261
 
 
262
 
                var property = config[key];
263
 
                                                        
264
 
                if (typeof property != 'undefined' && property.event) {
265
 
                        if (typeof value != 'undefined' && property.validator && ! property.validator(value)) { // validator
266
 
                                return false;
267
 
                        } else {
268
 
 
269
 
                                if (typeof value != 'undefined') {
270
 
                                        property.value = value;
271
 
                                } else {
272
 
                                        value = property.value;
273
 
                                }
274
 
 
275
 
                                var foundDuplicate = false;
276
 
 
277
 
                                for (var i=0;i<eventQueue.length;i++) {
278
 
                                        var queueItem = eventQueue[i];
279
 
 
280
 
                                        if (queueItem) {
281
 
                                                var queueItemKey = queueItem[0];
282
 
                                                var queueItemValue = queueItem[1];
283
 
                                                
284
 
                                                if (queueItemKey.toLowerCase() == key) {
285
 
                                                        // found a dupe... push to end of queue, null current item, and break
286
 
                                                        eventQueue[i] = null;
287
 
                                                        eventQueue.push([key, (typeof value != 'undefined' ? value : queueItemValue)]);
288
 
                                                        foundDuplicate = true;
289
 
                                                        break;
290
 
                                                }
291
 
                                        }
292
 
                                }
293
 
                                
294
 
                                if (! foundDuplicate && typeof value != 'undefined') { // this is a refire, or a new property in the queue
295
 
                                        eventQueue.push([key, value]);
296
 
                                }
297
 
                        }
298
 
 
299
 
                        if (property.supercedes) {
300
 
                                for (var s=0;s<property.supercedes.length;s++) {
301
 
                                        var supercedesCheck = property.supercedes[s];
302
 
 
303
 
                                        for (var q=0;q<eventQueue.length;q++) {
304
 
                                                var queueItemCheck = eventQueue[q];
305
 
 
306
 
                                                if (queueItemCheck) {
307
 
                                                        var queueItemCheckKey = queueItemCheck[0];
308
 
                                                        var queueItemCheckValue = queueItemCheck[1];
309
 
                                                        
310
 
                                                        if ( queueItemCheckKey.toLowerCase() == supercedesCheck.toLowerCase() ) {
311
 
                                                                eventQueue.push([queueItemCheckKey, queueItemCheckValue]);
312
 
                                                                eventQueue[q] = null;
313
 
                                                                break;
314
 
                                                        }
315
 
                                                }
316
 
                                        }
317
 
                                }
318
 
                        }
319
 
        
320
 
                        YAHOO.log("Config event queue: " + this.outputEventQueue(), "info");
321
 
 
322
 
                        return true;
323
 
                } else {
324
 
                        return false;
325
 
                }
326
 
        };
327
 
 
328
 
        /**
329
 
        * Fires the event for a property using the property's current value.
330
 
        * @method refireEvent
331
 
        * @param {String} key   The name of the property
332
 
        */
333
 
        this.refireEvent = function(key) {
334
 
                key = key.toLowerCase();
335
 
 
336
 
                var property = config[key];
337
 
                if (typeof property != 'undefined' && property.event && typeof property.value != 'undefined') {
338
 
                        if (this.queueInProgress) {
339
 
                                this.queueProperty(key);
340
 
                        } else {
341
 
                                fireEvent(key, property.value);
342
 
                        }
343
 
                }
344
 
        };
345
 
 
346
 
        /**
347
 
        * Applies a key-value Object literal to the configuration, replacing any existing values, and queueing the property events.
348
 
        * Although the values will be set, fireQueue() must be called for their associated events to execute.
349
 
        * @method applyConfig
350
 
        * @param {Object}       userConfig      The configuration Object literal
351
 
        * @param {Boolean}      init            When set to true, the initialConfig will be set to the userConfig passed in, so that calling a reset will reset the properties to the passed values.
352
 
        */
353
 
        this.applyConfig = function(userConfig, init) {
354
 
                if (init) {
355
 
                        initialConfig = userConfig;
356
 
                }
357
 
                for (var prop in userConfig) {
358
 
                        this.queueProperty(prop, userConfig[prop]);
359
 
                }
360
 
        };
361
 
 
362
 
        /**
363
 
        * Refires the events for all configuration properties using their current values.
364
 
        * @method refresh
365
 
        */
366
 
        this.refresh = function() {
367
 
                for (var prop in config) {
368
 
                        this.refireEvent(prop);
369
 
                }
370
 
        };
371
 
 
372
 
        /**
373
 
        * Fires the normalized list of queued property change events
374
 
        * @method fireQueue
375
 
        */
376
 
        this.fireQueue = function() {
377
 
                this.queueInProgress = true;
378
 
                for (var i=0;i<eventQueue.length;i++) {
379
 
                        var queueItem = eventQueue[i];
380
 
                        if (queueItem) {
381
 
                                var key = queueItem[0];
382
 
                                var value = queueItem[1];
383
 
                                
384
 
                                var property = config[key];
385
 
                                property.value = value;
386
 
 
387
 
                                fireEvent(key,value);
388
 
                        }
389
 
                }
390
 
                
391
 
                this.queueInProgress = false;
392
 
                eventQueue = [];
393
 
        };
394
 
 
395
 
        /**
396
 
        * Subscribes an external handler to the change event for any given property. 
397
 
        * @method subscribeToConfigEvent
398
 
        * @param {String}       key                     The property name
399
 
        * @param {Function}     handler         The handler function to use subscribe to the property's event
400
 
        * @param {Object}       obj                     The Object to use for scoping the event handler (see CustomEvent documentation)
401
 
        * @param {Boolean}      override        Optional. If true, will override "this" within the handler to map to the scope Object passed into the method.
402
 
        * @return {Boolean}                             True, if the subscription was successful, otherwise false.
403
 
        */      
404
 
        this.subscribeToConfigEvent = function(key, handler, obj, override) {
405
 
                key = key.toLowerCase();
406
 
 
407
 
                var property = config[key];
408
 
                if (typeof property != 'undefined' && property.event) {
409
 
                        if (! YAHOO.util.Config.alreadySubscribed(property.event, handler, obj)) {
410
 
                                property.event.subscribe(handler, obj, override);
411
 
                        }
412
 
                        return true;
413
 
                } else {
414
 
                        return false;
415
 
                }
416
 
        };
417
 
 
418
 
        /**
419
 
        * Unsubscribes an external handler from the change event for any given property. 
420
 
        * @method unsubscribeFromConfigEvent
421
 
        * @param {String}       key                     The property name
422
 
        * @param {Function}     handler         The handler function to use subscribe to the property's event
423
 
        * @param {Object}       obj                     The Object to use for scoping the event handler (see CustomEvent documentation)
424
 
        * @return {Boolean}                             True, if the unsubscription was successful, otherwise false.
425
 
        */
426
 
        this.unsubscribeFromConfigEvent = function(key, handler, obj) {
427
 
                key = key.toLowerCase();
428
 
 
429
 
                var property = config[key];
430
 
                if (typeof property != 'undefined' && property.event) {
431
 
                        return property.event.unsubscribe(handler, obj);
432
 
                } else {
433
 
                        return false;
434
 
                }
435
 
        };
436
 
 
437
 
        /**
438
 
        * Returns a string representation of the Config object
439
 
        * @method toString
440
 
        * @return {String}      The Config object in string format.
441
 
        */
442
 
        this.toString = function() {
443
 
                var output = "Config";
444
 
                if (this.owner) {
445
 
                        output += " [" + this.owner.toString() + "]";
446
 
                }
447
 
                return output;
448
 
        };
449
 
 
450
 
        /**
451
 
        * Returns a string representation of the Config object's current CustomEvent queue
452
 
        * @method outputEventQueue
453
 
        * @return {String}      The string list of CustomEvents currently queued for execution
454
 
        */
455
 
        this.outputEventQueue = function() {
456
 
                var output = "";
457
 
                for (var q=0;q<eventQueue.length;q++) {
458
 
                        var queueItem = eventQueue[q];
459
 
                        if (queueItem) {
460
 
                                output += queueItem[0] + "=" + queueItem[1] + ", ";
461
 
                        }
462
 
                }
463
 
                return output;
464
 
        };
465
 
};
466
 
 
467
 
/**
468
 
* Checks to determine if a particular function/Object pair are already subscribed to the specified CustomEvent
469
 
* @method YAHOO.util.Config.alreadySubscribed
470
 
* @static
471
 
* @param {YAHOO.util.CustomEvent} evt   The CustomEvent for which to check the subscriptions
472
 
* @param {Function}     fn      The function to look for in the subscribers list
473
 
* @param {Object}       obj     The execution scope Object for the subscription
474
 
* @return {Boolean}     true, if the function/Object pair is already subscribed to the CustomEvent passed in
475
 
*/
476
 
YAHOO.util.Config.alreadySubscribed = function(evt, fn, obj) {
477
 
        for (var e=0;e<evt.subscribers.length;e++) {
478
 
                var subsc = evt.subscribers[e];
479
 
                if (subsc && subsc.obj == obj && subsc.fn == fn) {
480
 
                        return true;
481
 
                }
482
 
        }
483
 
        return false;
484
 
};
485
 
 
486
 
/**
487
 
*  The Container family of components is designed to enable developers to create different kinds of content-containing modules on the web. Module and Overlay are the most basic containers, and they can be used directly or extended to build custom containers. Also part of the Container family are four UI controls that extend Module and Overlay: Tooltip, Panel, Dialog, and SimpleDialog.
488
 
* @module container
489
 
* @title Container
490
 
* @requires yahoo,dom,event,dragdrop,animation
491
 
*/
492
 
 
493
 
/**
494
 
* Module is a JavaScript representation of the Standard Module Format. Standard Module Format is a simple standard for markup containers where child nodes representing the header, body, and footer of the content are denoted using the CSS classes "hd", "bd", and "ft" respectively. Module is the base class for all other classes in the YUI Container package.
495
 
* @namespace YAHOO.widget
496
 
* @class Module
497
 
* @constructor
498
 
* @param {String} el                    The element ID representing the Module <em>OR</em>
499
 
* @param {HTMLElement} el               The element representing the Module
500
 
* @param {Object} userConfig    The configuration Object literal containing the configuration that should be set for this module. See configuration documentation for more details.
501
 
*/
502
 
YAHOO.widget.Module = function(el, userConfig) {
503
 
        if (el) { 
504
 
                this.init(el, userConfig); 
505
 
        } else {
506
 
                YAHOO.log("No element or element ID specified for Module instantiation", "error");
507
 
        }
508
 
};
509
 
 
510
 
/**
511
 
* Constant representing the prefix path to use for non-secure images
512
 
* @property YAHOO.widget.Module.IMG_ROOT
513
 
* @static
514
 
* @final
515
 
* @type String
516
 
*/
517
 
YAHOO.widget.Module.IMG_ROOT = "http://us.i1.yimg.com/us.yimg.com/i/";
518
 
 
519
 
/**
520
 
* Constant representing the prefix path to use for securely served images
521
 
* @property YAHOO.widget.Module.IMG_ROOT_SSL
522
 
* @static
523
 
* @final
524
 
* @type String
525
 
*/
526
 
YAHOO.widget.Module.IMG_ROOT_SSL = "https://a248.e.akamai.net/sec.yimg.com/i/";
527
 
 
528
 
/**
529
 
* Constant for the default CSS class name that represents a Module
530
 
* @property YAHOO.widget.Module.CSS_MODULE
531
 
* @static
532
 
* @final
533
 
* @type String
534
 
*/
535
 
YAHOO.widget.Module.CSS_MODULE = "module";
536
 
 
537
 
/**
538
 
* Constant representing the module header
539
 
* @property YAHOO.widget.Module.CSS_HEADER
540
 
* @static
541
 
* @final
542
 
* @type String
543
 
*/
544
 
YAHOO.widget.Module.CSS_HEADER = "hd";
545
 
 
546
 
/**
547
 
* Constant representing the module body
548
 
* @property YAHOO.widget.Module.CSS_BODY
549
 
* @static
550
 
* @final
551
 
* @type String
552
 
*/
553
 
YAHOO.widget.Module.CSS_BODY = "bd";
554
 
 
555
 
/**
556
 
* Constant representing the module footer
557
 
* @property YAHOO.widget.Module.CSS_FOOTER
558
 
* @static
559
 
* @final
560
 
* @type String
561
 
*/
562
 
YAHOO.widget.Module.CSS_FOOTER = "ft";
563
 
 
564
 
/**
565
 
* Constant representing the url for the "src" attribute of the iframe used to monitor changes to the browser's base font size
566
 
* @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
567
 
* @static
568
 
* @final
569
 
* @type String
570
 
*/
571
 
YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
572
 
 
573
 
/**
574
 
* Singleton CustomEvent fired when the font size is changed in the browser.
575
 
* Opera's "zoom" functionality currently does not support text size detection.
576
 
* @event YAHOO.widget.Module.textResizeEvent
577
 
*/      
578
 
YAHOO.widget.Module.textResizeEvent = new YAHOO.util.CustomEvent("textResize");
579
 
 
580
 
YAHOO.widget.Module.prototype = {
581
 
        /**
582
 
        * The class's constructor function
583
 
        * @property contructor
584
 
        * @type Function
585
 
        */
586
 
        constructor : YAHOO.widget.Module,
587
 
 
588
 
        /**
589
 
        * The main module element that contains the header, body, and footer
590
 
        * @property element
591
 
        * @type HTMLElement
592
 
        */
593
 
        element : null, 
594
 
 
595
 
        /**
596
 
        * The header element, denoted with CSS class "hd"
597
 
        * @property header
598
 
        * @type HTMLElement
599
 
        */
600
 
        header : null,
601
 
 
602
 
        /**
603
 
        * The body element, denoted with CSS class "bd"
604
 
        * @property body
605
 
        * @type HTMLElement
606
 
        */
607
 
        body : null,
608
 
 
609
 
        /**
610
 
        * The footer element, denoted with CSS class "ft"
611
 
        * @property footer
612
 
        * @type HTMLElement
613
 
        */
614
 
        footer : null,
615
 
 
616
 
        /**
617
 
        * The id of the element
618
 
        * @property id
619
 
        * @type String
620
 
        */
621
 
        id : null,
622
 
 
623
 
        /**
624
 
        * The String representing the image root
625
 
        * @property imageRoot
626
 
        * @type String
627
 
        */
628
 
        imageRoot : YAHOO.widget.Module.IMG_ROOT,
629
 
                
630
 
        /**
631
 
        * Initializes the custom events for Module which are fired automatically at appropriate times by the Module class.
632
 
        * @method initEvents
633
 
        */
634
 
        initEvents : function() {
635
 
 
636
 
                /**
637
 
                * CustomEvent fired prior to class initalization.
638
 
                * @event beforeInitEvent
639
 
                * @param {class} classRef       class reference of the initializing class, such as this.beforeInitEvent.fire(YAHOO.widget.Module)
640
 
                */
641
 
                this.beforeInitEvent = new YAHOO.util.CustomEvent("beforeInit");
642
 
 
643
 
                /**
644
 
                * CustomEvent fired after class initalization.
645
 
                * @event initEvent
646
 
                * @param {class} classRef       class reference of the initializing class, such as this.beforeInitEvent.fire(YAHOO.widget.Module)
647
 
                */              
648
 
                this.initEvent = new YAHOO.util.CustomEvent("init");
649
 
 
650
 
                /**
651
 
                * CustomEvent fired when the Module is appended to the DOM
652
 
                * @event appendEvent
653
 
                */
654
 
                this.appendEvent = new YAHOO.util.CustomEvent("append");
655
 
 
656
 
                /**
657
 
                * CustomEvent fired before the Module is rendered
658
 
                * @event beforeRenderEvent
659
 
                */
660
 
                this.beforeRenderEvent = new YAHOO.util.CustomEvent("beforeRender");
661
 
 
662
 
                /**
663
 
                * CustomEvent fired after the Module is rendered
664
 
                * @event renderEvent
665
 
                */
666
 
                this.renderEvent = new YAHOO.util.CustomEvent("render");
667
 
        
668
 
                /**
669
 
                * CustomEvent fired when the header content of the Module is modified
670
 
                * @event changeHeaderEvent
671
 
                * @param {String/HTMLElement} content   String/element representing the new header content
672
 
                */
673
 
                this.changeHeaderEvent = new YAHOO.util.CustomEvent("changeHeader");
674
 
                
675
 
                /**
676
 
                * CustomEvent fired when the body content of the Module is modified
677
 
                * @event changeBodyEvent
678
 
                * @param {String/HTMLElement} content   String/element representing the new body content
679
 
                */              
680
 
                this.changeBodyEvent = new YAHOO.util.CustomEvent("changeBody");
681
 
                
682
 
                /**
683
 
                * CustomEvent fired when the footer content of the Module is modified
684
 
                * @event changeFooterEvent
685
 
                * @param {String/HTMLElement} content   String/element representing the new footer content
686
 
                */
687
 
                this.changeFooterEvent = new YAHOO.util.CustomEvent("changeFooter");
688
 
 
689
 
                /**
690
 
                * CustomEvent fired when the content of the Module is modified
691
 
                * @event changeContentEvent
692
 
                */
693
 
                this.changeContentEvent = new YAHOO.util.CustomEvent("changeContent");
694
 
 
695
 
                /**
696
 
                * CustomEvent fired when the Module is destroyed
697
 
                * @event destroyEvent
698
 
                */
699
 
                this.destroyEvent = new YAHOO.util.CustomEvent("destroy");
700
 
                
701
 
                /**
702
 
                * CustomEvent fired before the Module is shown
703
 
                * @event beforeShowEvent
704
 
                */
705
 
                this.beforeShowEvent = new YAHOO.util.CustomEvent("beforeShow");
706
 
 
707
 
                /**
708
 
                * CustomEvent fired after the Module is shown
709
 
                * @event showEvent
710
 
                */
711
 
                this.showEvent = new YAHOO.util.CustomEvent("show");
712
 
 
713
 
                /**
714
 
                * CustomEvent fired before the Module is hidden
715
 
                * @event beforeHideEvent
716
 
                */
717
 
                this.beforeHideEvent = new YAHOO.util.CustomEvent("beforeHide");
718
 
 
719
 
                /**
720
 
                * CustomEvent fired after the Module is hidden
721
 
                * @event hideEvent
722
 
                */
723
 
                this.hideEvent = new YAHOO.util.CustomEvent("hide");
724
 
        }, 
725
 
 
726
 
        /**
727
 
        * String representing the current user-agent platform
728
 
        * @property platform
729
 
        * @type String
730
 
        */
731
 
        platform : function() {
732
 
                                        var ua = navigator.userAgent.toLowerCase();
733
 
                                        if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
734
 
                                                return "windows";
735
 
                                        } else if (ua.indexOf("macintosh") != -1) {
736
 
                                                return "mac";
737
 
                                        } else {
738
 
                                                return false;
739
 
                                        }
740
 
                                }(),
741
 
 
742
 
        /**
743
 
        * String representing the current user-agent browser
744
 
        * @property browser
745
 
        * @type String
746
 
        */
747
 
        browser : function() {
748
 
                        var ua = navigator.userAgent.toLowerCase();
749
 
                                  if (ua.indexOf('opera')!=-1) { // Opera (check first in case of spoof)
750
 
                                         return 'opera';
751
 
                                  } else if (ua.indexOf('msie 7')!=-1) { // IE7
752
 
                                         return 'ie7';
753
 
                                  } else if (ua.indexOf('msie') !=-1) { // IE
754
 
                                         return 'ie';
755
 
                                  } else if (ua.indexOf('safari')!=-1) { // Safari (check before Gecko because it includes "like Gecko")
756
 
                                         return 'safari';
757
 
                                  } else if (ua.indexOf('gecko') != -1) { // Gecko
758
 
                                         return 'gecko';
759
 
                                  } else {
760
 
                                         return false;
761
 
                                  }
762
 
                        }(),
763
 
 
764
 
        /**
765
 
        * Boolean representing whether or not the current browsing context is secure (https)
766
 
        * @property isSecure
767
 
        * @type Boolean
768
 
        */
769
 
        isSecure : function() {
770
 
                if (window.location.href.toLowerCase().indexOf("https") === 0) {
771
 
                        return true;
772
 
                } else {
773
 
                        return false;
774
 
                }
775
 
        }(),
776
 
 
777
 
        /**
778
 
        * Initializes the custom events for Module which are fired automatically at appropriate times by the Module class.
779
 
        */
780
 
        initDefaultConfig : function() {
781
 
                // Add properties //
782
 
                
783
 
                /**
784
 
                * Specifies whether the Module is visible on the page.
785
 
                * @config visible
786
 
                * @type Boolean
787
 
                * @default true
788
 
                */
789
 
                this.cfg.addProperty("visible", { value:true, handler:this.configVisible, validator:this.cfg.checkBoolean } );
790
 
                
791
 
                /**
792
 
                * Object or array of objects representing the ContainerEffect classes that are active for animating the container.
793
 
                * @config effect
794
 
                * @type Object
795
 
                * @default null
796
 
                */
797
 
                this.cfg.addProperty("effect", { suppressEvent:true, supercedes:["visible"] } );
798
 
                
799
 
                /**
800
 
                * Specifies whether to create a special proxy iframe to monitor for user font resizing in the document
801
 
                * @config monitorresize
802
 
                * @type Boolean
803
 
                * @default true
804
 
                */
805
 
                this.cfg.addProperty("monitorresize", { value:true, handler:this.configMonitorResize } );
806
 
        },
807
 
 
808
 
        /**
809
 
        * The Module class's initialization method, which is executed for Module and all of its subclasses. This method is automatically called by the constructor, and  sets up all DOM references for pre-existing markup, and creates required markup if it is not already present.
810
 
        * @method init
811
 
        * @param {String}       el      The element ID representing the Module <em>OR</em>
812
 
        * @param {HTMLElement}  el      The element representing the Module
813
 
        * @param {Object}       userConfig      The configuration Object literal containing the configuration that should be set for this module. See configuration documentation for more details.
814
 
        */
815
 
        init : function(el, userConfig) {
816
 
 
817
 
                this.initEvents();
818
 
 
819
 
                this.beforeInitEvent.fire(YAHOO.widget.Module);
820
 
 
821
 
                /**
822
 
                * The Module's Config object used for monitoring configuration properties.
823
 
                * @property cfg
824
 
                * @type YAHOO.util.Config
825
 
                */
826
 
                this.cfg = new YAHOO.util.Config(this);
827
 
                
828
 
                if (this.isSecure) {
829
 
                        this.imageRoot = YAHOO.widget.Module.IMG_ROOT_SSL;
830
 
                }
831
 
 
832
 
                if (typeof el == "string") {
833
 
                        var elId = el;
834
 
 
835
 
                        el = document.getElementById(el);
836
 
                        if (! el) {
837
 
                                el = document.createElement("DIV");
838
 
                                el.id = elId;
839
 
                        }
840
 
                }
841
 
 
842
 
                this.element = el;
843
 
                
844
 
                if (el.id) {
845
 
                        this.id = el.id;
846
 
                } 
847
 
 
848
 
                var childNodes = this.element.childNodes;
849
 
 
850
 
                if (childNodes) {
851
 
                        for (var i=0;i<childNodes.length;i++) {
852
 
                                var child = childNodes[i];
853
 
                                switch (child.className) {
854
 
                                        case YAHOO.widget.Module.CSS_HEADER:
855
 
                                                this.header = child;
856
 
                                                break;
857
 
                                        case YAHOO.widget.Module.CSS_BODY:
858
 
                                                this.body = child;
859
 
                                                break;
860
 
                                        case YAHOO.widget.Module.CSS_FOOTER:
861
 
                                                this.footer = child;
862
 
                                                break;
863
 
                                }
864
 
                        }
865
 
                }
866
 
 
867
 
                this.initDefaultConfig();
868
 
 
869
 
                YAHOO.util.Dom.addClass(this.element, YAHOO.widget.Module.CSS_MODULE);
870
 
 
871
 
                if (userConfig) {
872
 
                        this.cfg.applyConfig(userConfig, true);
873
 
                }
874
 
 
875
 
                // Subscribe to the fireQueue() method of Config so that any queued configuration changes are
876
 
                // excecuted upon render of the Module
877
 
                if (! YAHOO.util.Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) {
878
 
                        this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
879
 
                }
880
 
 
881
 
                this.initEvent.fire(YAHOO.widget.Module);
882
 
        },
883
 
 
884
 
        /**
885
 
        * Initialized an empty IFRAME that is placed out of the visible area that can be used to detect text resize.
886
 
        * @method initResizeMonitor
887
 
        */
888
 
        initResizeMonitor : function() {
889
 
 
890
 
        if(this.browser != "opera") {
891
 
 
892
 
            var resizeMonitor = document.getElementById("_yuiResizeMonitor");
893
 
    
894
 
            if (! resizeMonitor) {
895
 
    
896
 
                resizeMonitor = document.createElement("iframe");
897
 
    
898
 
                var bIE = (this.browser.indexOf("ie") === 0);
899
 
    
900
 
                if(this.isSecure && 
901
 
                   YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL && 
902
 
                   bIE) {
903
 
    
904
 
                  resizeMonitor.src = 
905
 
                       YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL;
906
 
    
907
 
                }                
908
 
 
909
 
                resizeMonitor.id = "_yuiResizeMonitor";
910
 
                resizeMonitor.style.visibility = "hidden";
911
 
                
912
 
                document.body.appendChild(resizeMonitor);
913
 
    
914
 
                resizeMonitor.style.width = "10em";
915
 
                resizeMonitor.style.height = "10em";
916
 
                resizeMonitor.style.position = "absolute";
917
 
                
918
 
                var nLeft = -1 * resizeMonitor.offsetWidth,
919
 
                    nTop = -1 * resizeMonitor.offsetHeight;
920
 
    
921
 
                resizeMonitor.style.top = nTop + "px";
922
 
                resizeMonitor.style.left =  nLeft + "px";
923
 
                resizeMonitor.style.borderStyle = "none";
924
 
                resizeMonitor.style.borderWidth = "0";
925
 
                YAHOO.util.Dom.setStyle(resizeMonitor, "opacity", "0");
926
 
                
927
 
                resizeMonitor.style.visibility = "visible";
928
 
    
929
 
                if(!bIE) {
930
 
    
931
 
                    var doc = resizeMonitor.contentWindow.document;
932
 
    
933
 
                    doc.open();
934
 
                    doc.close();
935
 
                
936
 
                }
937
 
            }
938
 
    
939
 
                        var fireTextResize = function() {
940
 
                                YAHOO.widget.Module.textResizeEvent.fire();
941
 
                        };
942
 
 
943
 
            if(resizeMonitor && resizeMonitor.contentWindow) {
944
 
                this.resizeMonitor = resizeMonitor;
945
 
                                
946
 
                                YAHOO.widget.Module.textResizeEvent.subscribe(this.onDomResize, this, true);
947
 
                                
948
 
                                if (! YAHOO.widget.Module.textResizeInitialized) {
949
 
                                        if (! YAHOO.util.Event.addListener(this.resizeMonitor.contentWindow, "resize", fireTextResize)) {
950
 
                                                // This will fail in IE if document.domain has changed, so we must change the listener to
951
 
                                                // use the resizeMonitor element instead
952
 
                                                YAHOO.util.Event.addListener(this.resizeMonitor, "resize", fireTextResize);
953
 
                                        }
954
 
                                        YAHOO.widget.Module.textResizeInitialized = true;
955
 
                                }
956
 
            }
957
 
        
958
 
        }
959
 
 
960
 
        },
961
 
 
962
 
        /**
963
 
        * Event handler fired when the resize monitor element is resized.
964
 
        * @method onDomResize
965
 
        * @param {DOMEvent} e   The DOM resize event
966
 
        * @param {Object} obj   The scope object passed to the handler
967
 
        */
968
 
        onDomResize : function(e, obj) { 
969
 
 
970
 
        var nLeft = -1 * this.resizeMonitor.offsetWidth,
971
 
            nTop = -1 * this.resizeMonitor.offsetHeight;
972
 
        
973
 
        this.resizeMonitor.style.top = nTop + "px";
974
 
        this.resizeMonitor.style.left =  nLeft + "px";
975
 
        
976
 
        },
977
 
 
978
 
        /**
979
 
        * Sets the Module's header content to the HTML specified, or appends the passed element to the header. If no header is present, one will be automatically created.
980
 
        * @method setHeader
981
 
        * @param {String}       headerContent   The HTML used to set the header <em>OR</em>
982
 
        * @param {HTMLElement}  headerContent   The HTMLElement to append to the header
983
 
        */      
984
 
        setHeader : function(headerContent) {
985
 
                if (! this.header) {
986
 
                        this.header = document.createElement("DIV");
987
 
                        this.header.className = YAHOO.widget.Module.CSS_HEADER;
988
 
                }
989
 
                
990
 
                if (typeof headerContent == "string") {
991
 
                        this.header.innerHTML = headerContent;
992
 
                } else {
993
 
                        this.header.innerHTML = "";
994
 
                        this.header.appendChild(headerContent);
995
 
                }
996
 
 
997
 
                this.changeHeaderEvent.fire(headerContent);
998
 
                this.changeContentEvent.fire();
999
 
        },
1000
 
 
1001
 
        /**
1002
 
        * Appends the passed element to the header. If no header is present, one will be automatically created.
1003
 
        * @method appendToHeader
1004
 
        * @param {HTMLElement}  element The element to append to the header
1005
 
        */      
1006
 
        appendToHeader : function(element) {
1007
 
                if (! this.header) {
1008
 
                        this.header = document.createElement("DIV");
1009
 
                        this.header.className = YAHOO.widget.Module.CSS_HEADER;
1010
 
                }
1011
 
                
1012
 
                this.header.appendChild(element);
1013
 
                this.changeHeaderEvent.fire(element);
1014
 
                this.changeContentEvent.fire();
1015
 
        },
1016
 
 
1017
 
        /**
1018
 
        * Sets the Module's body content to the HTML specified, or appends the passed element to the body. If no body is present, one will be automatically created.
1019
 
        * @method setBody
1020
 
        * @param {String}       bodyContent     The HTML used to set the body <em>OR</em>
1021
 
        * @param {HTMLElement}  bodyContent     The HTMLElement to append to the body
1022
 
        */              
1023
 
        setBody : function(bodyContent) {
1024
 
                if (! this.body) {
1025
 
                        this.body = document.createElement("DIV");
1026
 
                        this.body.className = YAHOO.widget.Module.CSS_BODY;
1027
 
                }
1028
 
 
1029
 
                if (typeof bodyContent == "string")
1030
 
                {
1031
 
                        this.body.innerHTML = bodyContent;
1032
 
                } else {
1033
 
                        this.body.innerHTML = "";
1034
 
                        this.body.appendChild(bodyContent);
1035
 
                }
1036
 
 
1037
 
                this.changeBodyEvent.fire(bodyContent);
1038
 
                this.changeContentEvent.fire();
1039
 
        },
1040
 
 
1041
 
        /**
1042
 
        * Appends the passed element to the body. If no body is present, one will be automatically created.
1043
 
        * @method appendToBody
1044
 
        * @param {HTMLElement}  element The element to append to the body
1045
 
        */
1046
 
        appendToBody : function(element) {
1047
 
                if (! this.body) {
1048
 
                        this.body = document.createElement("DIV");
1049
 
                        this.body.className = YAHOO.widget.Module.CSS_BODY;
1050
 
                }
1051
 
 
1052
 
                this.body.appendChild(element);
1053
 
                this.changeBodyEvent.fire(element);
1054
 
                this.changeContentEvent.fire();
1055
 
        },
1056
 
 
1057
 
        /**
1058
 
        * Sets the Module's footer content to the HTML specified, or appends the passed element to the footer. If no footer is present, one will be automatically created.
1059
 
        * @method setFooter
1060
 
        * @param {String}       footerContent   The HTML used to set the footer <em>OR</em>
1061
 
        * @param {HTMLElement}  footerContent   The HTMLElement to append to the footer
1062
 
        */      
1063
 
        setFooter : function(footerContent) {
1064
 
                if (! this.footer) {
1065
 
                        this.footer = document.createElement("DIV");
1066
 
                        this.footer.className = YAHOO.widget.Module.CSS_FOOTER;
1067
 
                }
1068
 
 
1069
 
                if (typeof footerContent == "string") {
1070
 
                        this.footer.innerHTML = footerContent;
1071
 
                } else {
1072
 
                        this.footer.innerHTML = "";
1073
 
                        this.footer.appendChild(footerContent);
1074
 
                }
1075
 
 
1076
 
                this.changeFooterEvent.fire(footerContent);
1077
 
                this.changeContentEvent.fire();
1078
 
        },
1079
 
 
1080
 
        /**
1081
 
        * Appends the passed element to the footer. If no footer is present, one will be automatically created.
1082
 
        * @method appendToFooter
1083
 
        * @param {HTMLElement}  element The element to append to the footer
1084
 
        */
1085
 
        appendToFooter : function(element) {
1086
 
                if (! this.footer) {
1087
 
                        this.footer = document.createElement("DIV");
1088
 
                        this.footer.className = YAHOO.widget.Module.CSS_FOOTER;
1089
 
                }
1090
 
 
1091
 
                this.footer.appendChild(element);
1092
 
                this.changeFooterEvent.fire(element);
1093
 
                this.changeContentEvent.fire();
1094
 
        },
1095
 
 
1096
 
        /**
1097
 
        * Renders the Module by inserting the elements that are not already in the main Module into their correct places. Optionally appends the Module to the specified node prior to the render's execution. NOTE: For Modules without existing markup, the appendToNode argument is REQUIRED. If this argument is ommitted and the current element is not present in the document, the function will return false, indicating that the render was a failure.
1098
 
        * @method render
1099
 
        * @param {String}       appendToNode    The element id to which the Module should be appended to prior to rendering <em>OR</em>
1100
 
        * @param {HTMLElement}  appendToNode    The element to which the Module should be appended to prior to rendering        
1101
 
        * @param {HTMLElement}  moduleElement   OPTIONAL. The element that represents the actual Standard Module container. 
1102
 
        * @return {Boolean} Success or failure of the render
1103
 
        */
1104
 
        render : function(appendToNode, moduleElement) {
1105
 
                this.beforeRenderEvent.fire();
1106
 
 
1107
 
                if (! moduleElement) {
1108
 
                        moduleElement = this.element;
1109
 
                }
1110
 
 
1111
 
                var me = this;
1112
 
                var appendTo = function(element) {
1113
 
                        if (typeof element == "string") {
1114
 
                                element = document.getElementById(element);
1115
 
                        }
1116
 
                        
1117
 
                        if (element) {
1118
 
                                element.appendChild(me.element);
1119
 
                                me.appendEvent.fire();
1120
 
                        }
1121
 
                };
1122
 
 
1123
 
                if (appendToNode) {
1124
 
                        appendTo(appendToNode);
1125
 
                } else { // No node was passed in. If the element is not pre-marked up, this fails
1126
 
                        if (! YAHOO.util.Dom.inDocument(this.element)) {
1127
 
                                YAHOO.log("Render failed. Must specify appendTo node if Module isn't already in the DOM.", "error");
1128
 
                                return false;
1129
 
                        }
1130
 
                }
1131
 
 
1132
 
                // Need to get everything into the DOM if it isn't already
1133
 
                
1134
 
                if (this.header && ! YAHOO.util.Dom.inDocument(this.header)) {
1135
 
                        // There is a header, but it's not in the DOM yet... need to add it
1136
 
                        var firstChild = moduleElement.firstChild;
1137
 
                        if (firstChild) { // Insert before first child if exists
1138
 
                                moduleElement.insertBefore(this.header, firstChild);
1139
 
                        } else { // Append to empty body because there are no children
1140
 
                                moduleElement.appendChild(this.header);
1141
 
                        }
1142
 
                }
1143
 
 
1144
 
                if (this.body && ! YAHOO.util.Dom.inDocument(this.body)) {
1145
 
                        // There is a body, but it's not in the DOM yet... need to add it
1146
 
                        if (this.footer && YAHOO.util.Dom.isAncestor(this.moduleElement, this.footer)) { // Insert before footer if exists in DOM
1147
 
                                moduleElement.insertBefore(this.body, this.footer);
1148
 
                        } else { // Append to element because there is no footer
1149
 
                                moduleElement.appendChild(this.body);
1150
 
                        }
1151
 
                }
1152
 
 
1153
 
                if (this.footer && ! YAHOO.util.Dom.inDocument(this.footer)) {
1154
 
                        // There is a footer, but it's not in the DOM yet... need to add it
1155
 
                        moduleElement.appendChild(this.footer);
1156
 
                }
1157
 
 
1158
 
                this.renderEvent.fire();
1159
 
                return true;
1160
 
        },
1161
 
 
1162
 
        /**
1163
 
        * Removes the Module element from the DOM and sets all child elements to null.
1164
 
        * @method destroy
1165
 
        */
1166
 
        destroy : function() {
1167
 
                var parent;
1168
 
 
1169
 
                if (this.element) {
1170
 
                        YAHOO.util.Event.purgeElement(this.element, true);
1171
 
                        parent = this.element.parentNode;
1172
 
                }
1173
 
                if (parent) {
1174
 
                        parent.removeChild(this.element);
1175
 
                }
1176
 
 
1177
 
                this.element = null;
1178
 
                this.header = null;
1179
 
                this.body = null;
1180
 
                this.footer = null;
1181
 
 
1182
 
                for (var e in this) {
1183
 
                        if (e instanceof YAHOO.util.CustomEvent) {
1184
 
                                e.unsubscribeAll();
1185
 
                        }
1186
 
                }
1187
 
 
1188
 
                YAHOO.widget.Module.textResizeEvent.unsubscribe(this.onDomResize, this);
1189
 
 
1190
 
                this.destroyEvent.fire();
1191
 
        },
1192
 
 
1193
 
        /**
1194
 
        * Shows the Module element by setting the visible configuration property to true. Also fires two events: beforeShowEvent prior to the visibility change, and showEvent after.
1195
 
        * @method show
1196
 
        */
1197
 
        show : function() {
1198
 
                this.cfg.setProperty("visible", true);
1199
 
        },
1200
 
 
1201
 
        /**
1202
 
        * Hides the Module element by setting the visible configuration property to false. Also fires two events: beforeHideEvent prior to the visibility change, and hideEvent after.
1203
 
        * @method hide
1204
 
        */
1205
 
        hide : function() {
1206
 
                this.cfg.setProperty("visible", false);
1207
 
        },
1208
 
 
1209
 
        // BUILT-IN EVENT HANDLERS FOR MODULE //
1210
 
 
1211
 
        /**
1212
 
        * Default event handler for changing the visibility property of a Module. By default, this is achieved by switching the "display" style between "block" and "none".
1213
 
        * This method is responsible for firing showEvent and hideEvent.
1214
 
        * @param {String} type  The CustomEvent type (usually the property name)
1215
 
        * @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1216
 
        * @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1217
 
        * @method configVisible
1218
 
        */
1219
 
        configVisible : function(type, args, obj) {
1220
 
                var visible = args[0];
1221
 
                if (visible) {
1222
 
                        this.beforeShowEvent.fire();
1223
 
                        YAHOO.util.Dom.setStyle(this.element, "display", "block");
1224
 
                        this.showEvent.fire();
1225
 
                } else {
1226
 
                        this.beforeHideEvent.fire();
1227
 
                        YAHOO.util.Dom.setStyle(this.element, "display", "none");
1228
 
                        this.hideEvent.fire();
1229
 
                }
1230
 
        },
1231
 
 
1232
 
        /**
1233
 
        * Default event handler for the "monitorresize" configuration property
1234
 
        * @param {String} type  The CustomEvent type (usually the property name)
1235
 
        * @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1236
 
        * @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1237
 
        * @method configMonitorResize
1238
 
        */
1239
 
        configMonitorResize : function(type, args, obj) {
1240
 
                var monitor = args[0];
1241
 
                if (monitor) {
1242
 
                        this.initResizeMonitor();
1243
 
                } else {
1244
 
                        YAHOO.widget.Module.textResizeEvent.unsubscribe(this.onDomResize, this, true);
1245
 
                        this.resizeMonitor = null;
1246
 
                }
1247
 
        }
1248
 
};
1249
 
 
1250
 
/**
1251
 
* Returns a String representation of the Object.
1252
 
* @method toString
1253
 
* @return {String}      The string representation of the Module
1254
 
*/ 
1255
 
YAHOO.widget.Module.prototype.toString = function() {
1256
 
        return "Module " + this.id;
1257
 
};
1258
 
 
1259
 
/**
1260
 
* Overlay is a Module that is absolutely positioned above the page flow. It has convenience methods for positioning and sizing, as well as options for controlling zIndex and constraining the Overlay's position to the current visible viewport. Overlay also contains a dynamicly generated IFRAME which is placed beneath it for Internet Explorer 6 and 5.x so that it will be properly rendered above SELECT elements.
1261
 
* @namespace YAHOO.widget
1262
 
* @class Overlay
1263
 
* @extends YAHOO.widget.Module
1264
 
* @param {String}       el      The element ID representing the Overlay <em>OR</em>
1265
 
* @param {HTMLElement}  el      The element representing the Overlay
1266
 
* @param {Object}       userConfig      The configuration object literal containing 10/23/2006the configuration that should be set for this Overlay. See configuration documentation for more details.
1267
 
* @constructor
1268
 
*/
1269
 
YAHOO.widget.Overlay = function(el, userConfig) {
1270
 
        YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
1271
 
};
1272
 
 
1273
 
YAHOO.extend(YAHOO.widget.Overlay, YAHOO.widget.Module);
1274
 
 
1275
 
/**
1276
 
* The URL that will be placed in the iframe
1277
 
* @property YAHOO.widget.Overlay.IFRAME_SRC
1278
 
* @static
1279
 
* @final
1280
 
* @type String
1281
 
*/
1282
 
YAHOO.widget.Overlay.IFRAME_SRC = "javascript:false;";
1283
 
 
1284
 
/**
1285
 
* Constant representing the top left corner of an element, used for configuring the context element alignment
1286
 
* @property YAHOO.widget.Overlay.TOP_LEFT
1287
 
* @static
1288
 
* @final
1289
 
* @type String
1290
 
*/
1291
 
YAHOO.widget.Overlay.TOP_LEFT = "tl";
1292
 
 
1293
 
/**
1294
 
* Constant representing the top right corner of an element, used for configuring the context element alignment
1295
 
* @property YAHOO.widget.Overlay.TOP_RIGHT
1296
 
* @static
1297
 
* @final
1298
 
* @type String
1299
 
*/
1300
 
YAHOO.widget.Overlay.TOP_RIGHT = "tr";
1301
 
 
1302
 
/**
1303
 
* Constant representing the top bottom left corner of an element, used for configuring the context element alignment
1304
 
* @property YAHOO.widget.Overlay.BOTTOM_LEFT
1305
 
* @static
1306
 
* @final
1307
 
* @type String
1308
 
*/
1309
 
YAHOO.widget.Overlay.BOTTOM_LEFT = "bl";
1310
 
 
1311
 
/**
1312
 
* Constant representing the bottom right corner of an element, used for configuring the context element alignment
1313
 
* @property YAHOO.widget.Overlay.BOTTOM_RIGHT
1314
 
* @static
1315
 
* @final
1316
 
* @type String
1317
 
*/
1318
 
YAHOO.widget.Overlay.BOTTOM_RIGHT = "br";
1319
 
 
1320
 
/**
1321
 
* Constant representing the default CSS class used for an Overlay
1322
 
* @property YAHOO.widget.Overlay.CSS_OVERLAY
1323
 
* @static
1324
 
* @final
1325
 
* @type String
1326
 
*/
1327
 
YAHOO.widget.Overlay.CSS_OVERLAY = "overlay";
1328
 
 
1329
 
/**
1330
 
* The Overlay initialization method, which is executed for Overlay and all of its subclasses. This method is automatically called by the constructor, and  sets up all DOM references for pre-existing markup, and creates required markup if it is not already present.
1331
 
* @method init
1332
 
* @param {String}       el      The element ID representing the Overlay <em>OR</em>
1333
 
* @param {HTMLElement}  el      The element representing the Overlay
1334
 
* @param {Object}       userConfig      The configuration object literal containing the configuration that should be set for this Overlay. See configuration documentation for more details.
1335
 
*/
1336
 
YAHOO.widget.Overlay.prototype.init = function(el, userConfig) {
1337
 
        YAHOO.widget.Overlay.superclass.init.call(this, el/*, userConfig*/);  // Note that we don't pass the user config in here yet because we only want it executed once, at the lowest subclass level
1338
 
        
1339
 
        this.beforeInitEvent.fire(YAHOO.widget.Overlay);
1340
 
 
1341
 
        YAHOO.util.Dom.addClass(this.element, YAHOO.widget.Overlay.CSS_OVERLAY);
1342
 
 
1343
 
        if (userConfig) {
1344
 
                this.cfg.applyConfig(userConfig, true);
1345
 
        }
1346
 
 
1347
 
        if (this.platform == "mac" && this.browser == "gecko") {
1348
 
                if (! YAHOO.util.Config.alreadySubscribed(this.showEvent,this.showMacGeckoScrollbars,this)) {
1349
 
                        this.showEvent.subscribe(this.showMacGeckoScrollbars,this,true);
1350
 
                }
1351
 
                if (! YAHOO.util.Config.alreadySubscribed(this.hideEvent,this.hideMacGeckoScrollbars,this)) {
1352
 
                        this.hideEvent.subscribe(this.hideMacGeckoScrollbars,this,true);
1353
 
                }
1354
 
        }
1355
 
 
1356
 
        this.initEvent.fire(YAHOO.widget.Overlay);
1357
 
 
1358
 
};
1359
 
 
1360
 
/**
1361
 
* Initializes the custom events for Overlay which are fired automatically at appropriate times by the Overlay class.
1362
 
* @method initEvents
1363
 
*/
1364
 
YAHOO.widget.Overlay.prototype.initEvents = function() {
1365
 
        YAHOO.widget.Overlay.superclass.initEvents.call(this);
1366
 
 
1367
 
        /**
1368
 
        * CustomEvent fired before the Overlay is moved.
1369
 
        * @event beforeMoveEvent
1370
 
        * @param {Number} x     x coordinate
1371
 
        * @param {Number} y     y coordinate
1372
 
        */
1373
 
        this.beforeMoveEvent = new YAHOO.util.CustomEvent("beforeMove", this);
1374
 
 
1375
 
        /**
1376
 
        * CustomEvent fired after the Overlay is moved.
1377
 
        * @event moveEvent
1378
 
        * @param {Number} x     x coordinate
1379
 
        * @param {Number} y     y coordinate
1380
 
        */
1381
 
        this.moveEvent = new YAHOO.util.CustomEvent("move", this);
1382
 
};
1383
 
 
1384
 
/**
1385
 
* Initializes the class's configurable properties which can be changed using the Overlay's Config object (cfg).
1386
 
* @method initDefaultConfig
1387
 
*/
1388
 
YAHOO.widget.Overlay.prototype.initDefaultConfig = function() {
1389
 
        YAHOO.widget.Overlay.superclass.initDefaultConfig.call(this);
1390
 
 
1391
 
        // Add overlay config properties //
1392
 
 
1393
 
        /**
1394
 
        * The absolute x-coordinate position of the Overlay
1395
 
        * @config x
1396
 
        * @type Number
1397
 
        * @default null
1398
 
        */      
1399
 
        this.cfg.addProperty("x", { handler:this.configX, validator:this.cfg.checkNumber, suppressEvent:true, supercedes:["iframe"] } );
1400
 
 
1401
 
        /**
1402
 
        * The absolute y-coordinate position of the Overlay
1403
 
        * @config y
1404
 
        * @type Number
1405
 
        * @default null
1406
 
        */      
1407
 
        this.cfg.addProperty("y", { handler:this.configY, validator:this.cfg.checkNumber, suppressEvent:true, supercedes:["iframe"] } );
1408
 
 
1409
 
        /**
1410
 
        * An array with the absolute x and y positions of the Overlay
1411
 
        * @config xy
1412
 
        * @type Number[]
1413
 
        * @default null
1414
 
        */      
1415
 
        this.cfg.addProperty("xy",{ handler:this.configXY, suppressEvent:true, supercedes:["iframe"] } );
1416
 
 
1417
 
        /**
1418
 
        * The array of context arguments for context-sensitive positioning. The format is: [id or element, element corner, context corner]. For example, setting this property to ["img1", "tl", "bl"] would align the Overlay's top left corner to the context element's bottom left corner.
1419
 
        * @config context
1420
 
        * @type Array
1421
 
        * @default null
1422
 
        */      
1423
 
        this.cfg.addProperty("context", { handler:this.configContext, suppressEvent:true, supercedes:["iframe"] } );
1424
 
 
1425
 
        /**
1426
 
        * True if the Overlay should be anchored to the center of the viewport.
1427
 
        * @config fixedcenter
1428
 
        * @type Boolean
1429
 
        * @default false
1430
 
        */
1431
 
        this.cfg.addProperty("fixedcenter", { value:false, handler:this.configFixedCenter, validator:this.cfg.checkBoolean, supercedes:["iframe","visible"] } );
1432
 
 
1433
 
        /**
1434
 
        * CSS width of the Overlay.
1435
 
        * @config width
1436
 
        * @type String
1437
 
        * @default null
1438
 
        */
1439
 
        this.cfg.addProperty("width", { handler:this.configWidth, suppressEvent:true, supercedes:["iframe"] } );
1440
 
 
1441
 
        /**
1442
 
        * CSS height of the Overlay.
1443
 
        * @config height
1444
 
        * @type String
1445
 
        * @default null
1446
 
        */
1447
 
        this.cfg.addProperty("height", { handler:this.configHeight, suppressEvent:true, supercedes:["iframe"] } );
1448
 
 
1449
 
        /**
1450
 
        * CSS z-index of the Overlay.
1451
 
        * @config zIndex
1452
 
        * @type Number
1453
 
        * @default null
1454
 
        */
1455
 
        this.cfg.addProperty("zIndex", { value:null, handler:this.configzIndex } );
1456
 
 
1457
 
        /**
1458
 
        * True if the Overlay should be prevented from being positioned out of the viewport.
1459
 
        * @config constraintoviewport
1460
 
        * @type Boolean
1461
 
        * @default false
1462
 
        */
1463
 
        this.cfg.addProperty("constraintoviewport", { value:false, handler:this.configConstrainToViewport, validator:this.cfg.checkBoolean, supercedes:["iframe","x","y","xy"] } );
1464
 
 
1465
 
        /**
1466
 
        * True if the Overlay should have an IFRAME shim (for correcting the select z-index bug in IE6 and below).
1467
 
        * @config iframe
1468
 
        * @type Boolean
1469
 
        * @default true for IE6 and below, false for all others
1470
 
        */
1471
 
        this.cfg.addProperty("iframe", { value:(this.browser == "ie" ? true : false), handler:this.configIframe, validator:this.cfg.checkBoolean, supercedes:["zIndex"] } );
1472
 
};
1473
 
 
1474
 
/**
1475
 
* Moves the Overlay to the specified position. This function is identical to calling this.cfg.setProperty("xy", [x,y]);
1476
 
* @method moveTo
1477
 
* @param {Number}       x       The Overlay's new x position
1478
 
* @param {Number}       y       The Overlay's new y position
1479
 
*/
1480
 
YAHOO.widget.Overlay.prototype.moveTo = function(x, y) {
1481
 
        this.cfg.setProperty("xy",[x,y]);
1482
 
};
1483
 
 
1484
 
/**
1485
 
* Adds a special CSS class to the Overlay when Mac/Gecko is in use, to work around a Gecko bug where
1486
 
* scrollbars cannot be hidden. See https://bugzilla.mozilla.org/show_bug.cgi?id=187435
1487
 
* @method hideMacGeckoScrollbars
1488
 
*/
1489
 
YAHOO.widget.Overlay.prototype.hideMacGeckoScrollbars = function() {
1490
 
        YAHOO.util.Dom.removeClass(this.element, "show-scrollbars");
1491
 
        YAHOO.util.Dom.addClass(this.element, "hide-scrollbars");
1492
 
};
1493
 
 
1494
 
/**
1495
 
* Removes a special CSS class from the Overlay when Mac/Gecko is in use, to work around a Gecko bug where
1496
 
* scrollbars cannot be hidden. See https://bugzilla.mozilla.org/show_bug.cgi?id=187435
1497
 
* @method showMacGeckoScrollbars
1498
 
*/
1499
 
YAHOO.widget.Overlay.prototype.showMacGeckoScrollbars = function() {
1500
 
        YAHOO.util.Dom.removeClass(this.element, "hide-scrollbars");
1501
 
        YAHOO.util.Dom.addClass(this.element, "show-scrollbars");
1502
 
};
1503
 
 
1504
 
// BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
1505
 
 
1506
 
/**
1507
 
* The default event handler fired when the "visible" property is changed. This method is responsible for firing showEvent and hideEvent.
1508
 
* @method configVisible
1509
 
* @param {String} type  The CustomEvent type (usually the property name)
1510
 
* @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1511
 
* @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1512
 
*/
1513
 
YAHOO.widget.Overlay.prototype.configVisible = function(type, args, obj) {
1514
 
        var visible = args[0];
1515
 
        var currentVis = YAHOO.util.Dom.getStyle(this.element, "visibility");
1516
 
 
1517
 
        if (currentVis == "inherit") { 
1518
 
                var e = this.element.parentNode;
1519
 
                while (e.nodeType != 9 && e.nodeType != 11) {
1520
 
                        currentVis = YAHOO.util.Dom.getStyle(e, "visibility");
1521
 
                        if (currentVis != "inherit") { break; }
1522
 
                        e = e.parentNode;
1523
 
                }
1524
 
                if (currentVis == "inherit") { 
1525
 
                        currentVis = "visible";
1526
 
                }
1527
 
        }
1528
 
 
1529
 
        var effect = this.cfg.getProperty("effect");
1530
 
 
1531
 
        var effectInstances = [];
1532
 
        if (effect) {
1533
 
                if (effect instanceof Array) {
1534
 
                        for (var i=0;i<effect.length;i++) {
1535
 
                                var eff = effect[i];
1536
 
                                effectInstances[effectInstances.length] = eff.effect(this, eff.duration);
1537
 
                        }
1538
 
                } else {
1539
 
                        effectInstances[effectInstances.length] = effect.effect(this, effect.duration);
1540
 
                }
1541
 
        }
1542
 
 
1543
 
        var isMacGecko = (this.platform == "mac" && this.browser == "gecko");
1544
 
 
1545
 
        if (visible) { // Show
1546
 
                if (isMacGecko) {
1547
 
                        this.showMacGeckoScrollbars();
1548
 
                }       
1549
 
 
1550
 
                if (effect) { // Animate in
1551
 
                        if (visible) { // Animate in if not showing
1552
 
                                if (currentVis != "visible" || currentVis === "") {
1553
 
                                        this.beforeShowEvent.fire();
1554
 
                                        for (var j=0;j<effectInstances.length;j++) {
1555
 
                                                var ei = effectInstances[j];
1556
 
                                                if (j === 0 && ! YAHOO.util.Config.alreadySubscribed(ei.animateInCompleteEvent,this.showEvent.fire,this.showEvent)) {
1557
 
                                                        ei.animateInCompleteEvent.subscribe(this.showEvent.fire,this.showEvent,true); // Delegate showEvent until end of animateInComplete
1558
 
                                                }
1559
 
                                                ei.animateIn();
1560
 
                                        }
1561
 
                                }
1562
 
                        }
1563
 
                } else { // Show
1564
 
                        if (currentVis != "visible" || currentVis === "") {
1565
 
                                this.beforeShowEvent.fire();
1566
 
                                YAHOO.util.Dom.setStyle(this.element, "visibility", "visible");
1567
 
                                this.cfg.refireEvent("iframe");
1568
 
                                this.showEvent.fire();
1569
 
                        }
1570
 
                }
1571
 
 
1572
 
        } else { // Hide
1573
 
                if (isMacGecko) {
1574
 
                        this.hideMacGeckoScrollbars();
1575
 
                }       
1576
 
 
1577
 
                if (effect) { // Animate out if showing
1578
 
                        if (currentVis == "visible") {
1579
 
                                this.beforeHideEvent.fire();
1580
 
                                for (var k=0;k<effectInstances.length;k++) {
1581
 
                                        var h = effectInstances[k];
1582
 
                                        if (k === 0 && ! YAHOO.util.Config.alreadySubscribed(h.animateOutCompleteEvent,this.hideEvent.fire,this.hideEvent)) {                           
1583
 
                                                h.animateOutCompleteEvent.subscribe(this.hideEvent.fire,this.hideEvent,true); // Delegate hideEvent until end of animateOutComplete
1584
 
                                        }
1585
 
                                        h.animateOut();
1586
 
                                }
1587
 
                        } else if (currentVis === "") {
1588
 
                                YAHOO.util.Dom.setStyle(this.element, "visibility", "hidden");
1589
 
                        }
1590
 
                } else { // Simple hide
1591
 
                        if (currentVis == "visible" || currentVis === "") {
1592
 
                                this.beforeHideEvent.fire();
1593
 
                                YAHOO.util.Dom.setStyle(this.element, "visibility", "hidden");
1594
 
                                this.cfg.refireEvent("iframe");
1595
 
                                this.hideEvent.fire();
1596
 
                        }
1597
 
                }       
1598
 
        }
1599
 
};
1600
 
 
1601
 
/**
1602
 
* Center event handler used for centering on scroll/resize, but only if the Overlay is visible
1603
 
* @method doCenterOnDOMEvent
1604
 
*/
1605
 
YAHOO.widget.Overlay.prototype.doCenterOnDOMEvent = function() {
1606
 
        if (this.cfg.getProperty("visible")) {
1607
 
                this.center();
1608
 
        }
1609
 
};
1610
 
 
1611
 
/**
1612
 
* The default event handler fired when the "fixedcenter" property is changed.
1613
 
* @method configFixedCenter
1614
 
* @param {String} type  The CustomEvent type (usually the property name)
1615
 
* @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1616
 
* @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1617
 
*/
1618
 
YAHOO.widget.Overlay.prototype.configFixedCenter = function(type, args, obj) {
1619
 
        var val = args[0];
1620
 
 
1621
 
        if (val) {
1622
 
                this.center();
1623
 
                        
1624
 
                if (! YAHOO.util.Config.alreadySubscribed(this.beforeShowEvent, this.center, this)) {
1625
 
                        this.beforeShowEvent.subscribe(this.center, this, true);
1626
 
                }
1627
 
                
1628
 
                if (! YAHOO.util.Config.alreadySubscribed(YAHOO.widget.Overlay.windowResizeEvent, this.doCenterOnDOMEvent, this)) {
1629
 
                        YAHOO.widget.Overlay.windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
1630
 
                }
1631
 
 
1632
 
                if (! YAHOO.util.Config.alreadySubscribed(YAHOO.widget.Overlay.windowScrollEvent, this.doCenterOnDOMEvent, this)) {
1633
 
                        YAHOO.widget.Overlay.windowScrollEvent.subscribe( this.doCenterOnDOMEvent, this, true);
1634
 
                }
1635
 
        } else {
1636
 
                YAHOO.widget.Overlay.windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
1637
 
                YAHOO.widget.Overlay.windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
1638
 
        }
1639
 
};
1640
 
 
1641
 
/**
1642
 
* The default event handler fired when the "height" property is changed.
1643
 
* @method configHeight
1644
 
* @param {String} type  The CustomEvent type (usually the property name)
1645
 
* @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1646
 
* @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1647
 
*/
1648
 
YAHOO.widget.Overlay.prototype.configHeight = function(type, args, obj) {
1649
 
        var height = args[0];
1650
 
        var el = this.element;
1651
 
        YAHOO.util.Dom.setStyle(el, "height", height);
1652
 
        this.cfg.refireEvent("iframe");
1653
 
};
1654
 
 
1655
 
/**
1656
 
* The default event handler fired when the "width" property is changed.
1657
 
* @method configWidth
1658
 
* @param {String} type  The CustomEvent type (usually the property name)
1659
 
* @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1660
 
* @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1661
 
*/
1662
 
YAHOO.widget.Overlay.prototype.configWidth = function(type, args, obj) {
1663
 
        var width = args[0];
1664
 
        var el = this.element;
1665
 
        YAHOO.util.Dom.setStyle(el, "width", width);
1666
 
        this.cfg.refireEvent("iframe");
1667
 
};
1668
 
 
1669
 
/**
1670
 
* The default event handler fired when the "zIndex" property is changed.
1671
 
* @method configzIndex
1672
 
* @param {String} type  The CustomEvent type (usually the property name)
1673
 
* @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1674
 
* @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1675
 
*/
1676
 
YAHOO.widget.Overlay.prototype.configzIndex = function(type, args, obj) {
1677
 
        var zIndex = args[0];
1678
 
 
1679
 
        var el = this.element;
1680
 
 
1681
 
        if (! zIndex) {
1682
 
                zIndex = YAHOO.util.Dom.getStyle(el, "zIndex");
1683
 
                if (! zIndex || isNaN(zIndex)) {
1684
 
                        zIndex = 0;
1685
 
                }
1686
 
        }
1687
 
 
1688
 
        if (this.iframe) {
1689
 
                if (zIndex <= 0) {
1690
 
                        zIndex = 1;
1691
 
                }
1692
 
                YAHOO.util.Dom.setStyle(this.iframe, "zIndex", (zIndex-1));
1693
 
        }
1694
 
 
1695
 
        YAHOO.util.Dom.setStyle(el, "zIndex", zIndex);
1696
 
        this.cfg.setProperty("zIndex", zIndex, true);
1697
 
};
1698
 
 
1699
 
/**
1700
 
* The default event handler fired when the "xy" property is changed.
1701
 
* @method configXY
1702
 
* @param {String} type  The CustomEvent type (usually the property name)
1703
 
* @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1704
 
* @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1705
 
*/
1706
 
YAHOO.widget.Overlay.prototype.configXY = function(type, args, obj) {
1707
 
        var pos = args[0];
1708
 
        var x = pos[0];
1709
 
        var y = pos[1];
1710
 
 
1711
 
        this.cfg.setProperty("x", x);
1712
 
        this.cfg.setProperty("y", y);
1713
 
 
1714
 
        this.beforeMoveEvent.fire([x,y]);
1715
 
 
1716
 
        x = this.cfg.getProperty("x");
1717
 
        y = this.cfg.getProperty("y");
1718
 
 
1719
 
        YAHOO.log("xy: " + [x,y], "iframe");
1720
 
 
1721
 
        this.cfg.refireEvent("iframe");
1722
 
        this.moveEvent.fire([x,y]);
1723
 
};
1724
 
 
1725
 
/**
1726
 
* The default event handler fired when the "x" property is changed.
1727
 
* @method configX
1728
 
* @param {String} type  The CustomEvent type (usually the property name)
1729
 
* @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1730
 
* @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1731
 
*/
1732
 
YAHOO.widget.Overlay.prototype.configX = function(type, args, obj) {
1733
 
        var x = args[0];
1734
 
        var y = this.cfg.getProperty("y");
1735
 
 
1736
 
        this.cfg.setProperty("x", x, true);
1737
 
        this.cfg.setProperty("y", y, true);
1738
 
 
1739
 
        this.beforeMoveEvent.fire([x,y]);
1740
 
 
1741
 
        x = this.cfg.getProperty("x");
1742
 
        y = this.cfg.getProperty("y");
1743
 
 
1744
 
        YAHOO.util.Dom.setX(this.element, x, true);
1745
 
        
1746
 
        this.cfg.setProperty("xy", [x, y], true);
1747
 
 
1748
 
        this.cfg.refireEvent("iframe");
1749
 
        this.moveEvent.fire([x, y]);
1750
 
};
1751
 
 
1752
 
/**
1753
 
* The default event handler fired when the "y" property is changed.
1754
 
* @method configY
1755
 
* @param {String} type  The CustomEvent type (usually the property name)
1756
 
* @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1757
 
* @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1758
 
*/
1759
 
YAHOO.widget.Overlay.prototype.configY = function(type, args, obj) {
1760
 
        var x = this.cfg.getProperty("x");
1761
 
        var y = args[0];
1762
 
 
1763
 
        this.cfg.setProperty("x", x, true);
1764
 
        this.cfg.setProperty("y", y, true);
1765
 
 
1766
 
        this.beforeMoveEvent.fire([x,y]);
1767
 
 
1768
 
        x = this.cfg.getProperty("x");
1769
 
        y = this.cfg.getProperty("y");
1770
 
 
1771
 
        YAHOO.util.Dom.setY(this.element, y, true);
1772
 
 
1773
 
        this.cfg.setProperty("xy", [x, y], true);
1774
 
 
1775
 
        this.cfg.refireEvent("iframe");
1776
 
        this.moveEvent.fire([x, y]);
1777
 
};
1778
 
 
1779
 
/**
1780
 
* Shows the iframe shim, if it has been enabled
1781
 
* @method showIframe
1782
 
*/
1783
 
YAHOO.widget.Overlay.prototype.showIframe = function() {
1784
 
        if (this.iframe) {
1785
 
                this.iframe.style.display = "block";
1786
 
        }
1787
 
};
1788
 
 
1789
 
/**
1790
 
* Hides the iframe shim, if it has been enabled
1791
 
* @method hideIframe
1792
 
*/
1793
 
YAHOO.widget.Overlay.prototype.hideIframe = function() {
1794
 
        if (this.iframe) {
1795
 
                this.iframe.style.display = "none";
1796
 
        }
1797
 
};
1798
 
 
1799
 
/**
1800
 
* The default event handler fired when the "iframe" property is changed.
1801
 
* @method configIframe
1802
 
* @param {String} type  The CustomEvent type (usually the property name)
1803
 
* @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1804
 
* @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1805
 
*/
1806
 
YAHOO.widget.Overlay.prototype.configIframe = function(type, args, obj) {
1807
 
 
1808
 
        var val = args[0];
1809
 
 
1810
 
        if (val) { // IFRAME shim is enabled
1811
 
 
1812
 
                if (! YAHOO.util.Config.alreadySubscribed(this.showEvent, this.showIframe, this)) {
1813
 
                        this.showEvent.subscribe(this.showIframe, this, true);
1814
 
                }
1815
 
                if (! YAHOO.util.Config.alreadySubscribed(this.hideEvent, this.hideIframe, this)) {
1816
 
                        this.hideEvent.subscribe(this.hideIframe, this, true);
1817
 
                }
1818
 
 
1819
 
                var x = this.cfg.getProperty("x");
1820
 
                var y = this.cfg.getProperty("y");
1821
 
 
1822
 
                if (! x || ! y) {
1823
 
                        this.syncPosition();
1824
 
                        x = this.cfg.getProperty("x");
1825
 
                        y = this.cfg.getProperty("y");
1826
 
                }
1827
 
 
1828
 
                YAHOO.log("iframe positioning to: " + [x,y], "iframe");
1829
 
 
1830
 
                if (! isNaN(x) && ! isNaN(y)) {
1831
 
                        if (! this.iframe) {
1832
 
                                this.iframe = document.createElement("iframe");
1833
 
                                if (this.isSecure) {
1834
 
                                        this.iframe.src = YAHOO.widget.Overlay.IFRAME_SRC;
1835
 
                                }
1836
 
                                
1837
 
                                var parent = this.element.parentNode;
1838
 
                                if (parent) {
1839
 
                                        parent.appendChild(this.iframe);
1840
 
                                } else {
1841
 
                                        document.body.appendChild(this.iframe);
1842
 
                                }
1843
 
 
1844
 
                                YAHOO.util.Dom.setStyle(this.iframe, "position", "absolute");
1845
 
                                YAHOO.util.Dom.setStyle(this.iframe, "border", "none");
1846
 
                                YAHOO.util.Dom.setStyle(this.iframe, "margin", "0");
1847
 
                                YAHOO.util.Dom.setStyle(this.iframe, "padding", "0");
1848
 
                                YAHOO.util.Dom.setStyle(this.iframe, "opacity", "0");
1849
 
                                if (this.cfg.getProperty("visible")) {
1850
 
                                        this.showIframe();
1851
 
                                } else {
1852
 
                                        this.hideIframe();
1853
 
                                }
1854
 
                        }
1855
 
                        
1856
 
                        var iframeDisplay = YAHOO.util.Dom.getStyle(this.iframe, "display");
1857
 
 
1858
 
                        if (iframeDisplay == "none") {
1859
 
                                this.iframe.style.display = "block";
1860
 
                        }
1861
 
 
1862
 
                        YAHOO.util.Dom.setXY(this.iframe, [x,y]);
1863
 
 
1864
 
                        var width = this.element.clientWidth;
1865
 
                        var height = this.element.clientHeight;
1866
 
 
1867
 
                        YAHOO.util.Dom.setStyle(this.iframe, "width", (width+2) + "px");
1868
 
                        YAHOO.util.Dom.setStyle(this.iframe, "height", (height+2) + "px");
1869
 
 
1870
 
                        if (iframeDisplay == "none") {
1871
 
                                this.iframe.style.display = "none";
1872
 
                        }
1873
 
                }
1874
 
        } else {
1875
 
                if (this.iframe) {
1876
 
                        this.iframe.style.display = "none";
1877
 
                }
1878
 
                this.showEvent.unsubscribe(this.showIframe, this);
1879
 
                this.hideEvent.unsubscribe(this.hideIframe, this);
1880
 
        }
1881
 
};
1882
 
 
1883
 
 
1884
 
/**
1885
 
* The default event handler fired when the "constraintoviewport" property is changed.
1886
 
* @method configConstrainToViewport
1887
 
* @param {String} type  The CustomEvent type (usually the property name)
1888
 
* @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1889
 
* @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1890
 
*/
1891
 
YAHOO.widget.Overlay.prototype.configConstrainToViewport = function(type, args, obj) {
1892
 
        var val = args[0];
1893
 
        if (val) {
1894
 
                if (! YAHOO.util.Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
1895
 
                        this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
1896
 
                }
1897
 
        } else {
1898
 
                this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
1899
 
        }
1900
 
};
1901
 
 
1902
 
/**
1903
 
* The default event handler fired when the "context" property is changed.
1904
 
* @method configContext
1905
 
* @param {String} type  The CustomEvent type (usually the property name)
1906
 
* @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1907
 
* @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1908
 
*/
1909
 
YAHOO.widget.Overlay.prototype.configContext = function(type, args, obj) {
1910
 
        var contextArgs = args[0];
1911
 
 
1912
 
        if (contextArgs) {
1913
 
                var contextEl = contextArgs[0];
1914
 
                var elementMagnetCorner = contextArgs[1];
1915
 
                var contextMagnetCorner = contextArgs[2];
1916
 
 
1917
 
                if (contextEl) {
1918
 
                        if (typeof contextEl == "string") {
1919
 
                                this.cfg.setProperty("context", [document.getElementById(contextEl),elementMagnetCorner,contextMagnetCorner], true);
1920
 
                        }
1921
 
                        
1922
 
                        if (elementMagnetCorner && contextMagnetCorner) {
1923
 
                                this.align(elementMagnetCorner, contextMagnetCorner);
1924
 
                        }
1925
 
                }       
1926
 
        }
1927
 
};
1928
 
 
1929
 
 
1930
 
// END BUILT-IN PROPERTY EVENT HANDLERS //
1931
 
 
1932
 
/**
1933
 
* Aligns the Overlay to its context element using the specified corner points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, and BOTTOM_RIGHT.
1934
 
* @method align
1935
 
* @param {String} elementAlign          The String representing the corner of the Overlay that should be aligned to the context element
1936
 
* @param {String} contextAlign          The corner of the context element that the elementAlign corner should stick to.
1937
 
*/
1938
 
YAHOO.widget.Overlay.prototype.align = function(elementAlign, contextAlign) {
1939
 
        var contextArgs = this.cfg.getProperty("context");
1940
 
        if (contextArgs) {
1941
 
                var context = contextArgs[0];
1942
 
                
1943
 
                var element = this.element;
1944
 
                var me = this;
1945
 
 
1946
 
                if (! elementAlign) {
1947
 
                        elementAlign = contextArgs[1];
1948
 
                }
1949
 
 
1950
 
                if (! contextAlign) {
1951
 
                        contextAlign = contextArgs[2];
1952
 
                }
1953
 
 
1954
 
                if (element && context) {
1955
 
                        var elementRegion = YAHOO.util.Dom.getRegion(element);
1956
 
                        var contextRegion = YAHOO.util.Dom.getRegion(context);
1957
 
 
1958
 
                        var doAlign = function(v,h) {
1959
 
                                switch (elementAlign) {
1960
 
                                        case YAHOO.widget.Overlay.TOP_LEFT:
1961
 
                                                me.moveTo(h,v);
1962
 
                                                break;
1963
 
                                        case YAHOO.widget.Overlay.TOP_RIGHT:
1964
 
                                                me.moveTo(h-element.offsetWidth,v);
1965
 
                                                break;
1966
 
                                        case YAHOO.widget.Overlay.BOTTOM_LEFT:
1967
 
                                                me.moveTo(h,v-element.offsetHeight);
1968
 
                                                break;
1969
 
                                        case YAHOO.widget.Overlay.BOTTOM_RIGHT:
1970
 
                                                me.moveTo(h-element.offsetWidth,v-element.offsetHeight);
1971
 
                                                break;
1972
 
                                }
1973
 
                        };
1974
 
 
1975
 
                        switch (contextAlign) {
1976
 
                                case YAHOO.widget.Overlay.TOP_LEFT:
1977
 
                                        doAlign(contextRegion.top, contextRegion.left);
1978
 
                                        break;
1979
 
                                case YAHOO.widget.Overlay.TOP_RIGHT:
1980
 
                                        doAlign(contextRegion.top, contextRegion.right);
1981
 
                                        break;          
1982
 
                                case YAHOO.widget.Overlay.BOTTOM_LEFT:
1983
 
                                        doAlign(contextRegion.bottom, contextRegion.left);
1984
 
                                        break;
1985
 
                                case YAHOO.widget.Overlay.BOTTOM_RIGHT:
1986
 
                                        doAlign(contextRegion.bottom, contextRegion.right);
1987
 
                                        break;
1988
 
                        }
1989
 
                }
1990
 
        }
1991
 
};
1992
 
 
1993
 
/**
1994
 
* The default event handler executed when the moveEvent is fired, if the "constraintoviewport" is set to true.
1995
 
* @method enforceConstraints
1996
 
* @param {String} type  The CustomEvent type (usually the property name)
1997
 
* @param {Object[]}     args    The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property.
1998
 
* @param {Object} obj   The scope object. For configuration handlers, this will usually equal the owner.
1999
 
*/
2000
 
YAHOO.widget.Overlay.prototype.enforceConstraints = function(type, args, obj) {
2001
 
        var pos = args[0];
2002
 
 
2003
 
        var x = pos[0];
2004
 
        var y = pos[1];
2005
 
 
2006
 
        var offsetHeight = this.element.offsetHeight;
2007
 
        var offsetWidth = this.element.offsetWidth;
2008
 
 
2009
 
        var viewPortWidth = YAHOO.util.Dom.getViewportWidth();
2010
 
        var viewPortHeight = YAHOO.util.Dom.getViewportHeight();
2011
 
 
2012
 
        var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
2013
 
        var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
2014
 
 
2015
 
        var topConstraint = scrollY + 10;
2016
 
        var leftConstraint = scrollX + 10;
2017
 
        var bottomConstraint = scrollY + viewPortHeight - offsetHeight - 10;
2018
 
        var rightConstraint = scrollX + viewPortWidth - offsetWidth - 10;
2019
 
        
2020
 
        if (x < leftConstraint) {
2021
 
                x = leftConstraint;
2022
 
        } else if (x > rightConstraint) {
2023
 
                x = rightConstraint;
2024
 
        }
2025
 
 
2026
 
        if (y < topConstraint) {
2027
 
                y = topConstraint;
2028
 
        } else if (y > bottomConstraint) {
2029
 
                y = bottomConstraint;
2030
 
        }
2031
 
 
2032
 
        this.cfg.setProperty("x", x, true);
2033
 
        this.cfg.setProperty("y", y, true);
2034
 
        this.cfg.setProperty("xy", [x,y], true);
2035
 
};
2036
 
 
2037
 
/**
2038
 
* Centers the container in the viewport.
2039
 
* @method center
2040
 
*/
2041
 
YAHOO.widget.Overlay.prototype.center = function() {
2042
 
        var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
2043
 
        var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
2044
 
 
2045
 
        var viewPortWidth = YAHOO.util.Dom.getClientWidth();
2046
 
        var viewPortHeight = YAHOO.util.Dom.getClientHeight();
2047
 
 
2048
 
        var elementWidth = this.element.offsetWidth;
2049
 
        var elementHeight = this.element.offsetHeight;
2050
 
 
2051
 
        var x = (viewPortWidth / 2) - (elementWidth / 2) + scrollX;
2052
 
        var y = (viewPortHeight / 2) - (elementHeight / 2) + scrollY;
2053
 
                
2054
 
        this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
2055
 
 
2056
 
        this.cfg.refireEvent("iframe");
2057
 
};
2058
 
 
2059
 
/**
2060
 
* Synchronizes the Panel's "xy", "x", and "y" properties with the Panel's position in the DOM. This is primarily used to update position information during drag & drop.
2061
 
* @method syncPosition
2062
 
*/
2063
 
YAHOO.widget.Overlay.prototype.syncPosition = function() {
2064
 
        var pos = YAHOO.util.Dom.getXY(this.element);
2065
 
        this.cfg.setProperty("x", pos[0], true);
2066
 
        this.cfg.setProperty("y", pos[1], true);
2067
 
        this.cfg.setProperty("xy", pos, true);
2068
 
};
2069
 
 
2070
 
/**
2071
 
* Event handler fired when the resize monitor element is resized.
2072
 
* @method onDomResize
2073
 
* @param {DOMEvent} e   The resize DOM event
2074
 
* @param {Object} obj   The scope object
2075
 
*/
2076
 
YAHOO.widget.Overlay.prototype.onDomResize = function(e, obj) {
2077
 
        YAHOO.widget.Overlay.superclass.onDomResize.call(this, e, obj);
2078
 
        var me = this;
2079
 
        setTimeout(function() {
2080
 
                me.syncPosition();
2081
 
                me.cfg.refireEvent("iframe");
2082
 
                me.cfg.refireEvent("context");
2083
 
        }, 0);
2084
 
};
2085
 
 
2086
 
/**
2087
 
* Removes the Overlay element from the DOM and sets all child elements to null.
2088
 
* @method destroy
2089
 
*/
2090
 
YAHOO.widget.Overlay.prototype.destroy = function() {
2091
 
        if (this.iframe) {
2092
 
                this.iframe.parentNode.removeChild(this.iframe);
2093
 
        }
2094
 
        
2095
 
        this.iframe = null;
2096
 
 
2097
 
        YAHOO.widget.Overlay.windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2098
 
        YAHOO.widget.Overlay.windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2099
 
 
2100
 
        YAHOO.widget.Overlay.superclass.destroy.call(this);  
2101
 
};
2102
 
 
2103
 
/**
2104
 
* Returns a String representation of the object.
2105
 
* @method toString
2106
 
* @return {String} The string representation of the Overlay.
2107
 
*/ 
2108
 
YAHOO.widget.Overlay.prototype.toString = function() {
2109
 
        return "Overlay " + this.id;
2110
 
};
2111
 
 
2112
 
/**
2113
 
* A singleton CustomEvent used for reacting to the DOM event for window scroll
2114
 
* @event YAHOO.widget.Overlay.windowScrollEvent
2115
 
*/
2116
 
YAHOO.widget.Overlay.windowScrollEvent = new YAHOO.util.CustomEvent("windowScroll");
2117
 
 
2118
 
/**
2119
 
* A singleton CustomEvent used for reacting to the DOM event for window resize
2120
 
* @event YAHOO.widget.Overlay.windowResizeEvent
2121
 
*/
2122
 
YAHOO.widget.Overlay.windowResizeEvent = new YAHOO.util.CustomEvent("windowResize");
2123
 
 
2124
 
/**
2125
 
* The DOM event handler used to fire the CustomEvent for window scroll
2126
 
* @method YAHOO.widget.Overlay.windowScrollHandler
2127
 
* @static
2128
 
* @param {DOMEvent} e The DOM scroll event
2129
 
*/
2130
 
YAHOO.widget.Overlay.windowScrollHandler = function(e) {
2131
 
        if (YAHOO.widget.Module.prototype.browser == "ie" || YAHOO.widget.Module.prototype.browser == "ie7") {
2132
 
                if (! window.scrollEnd) {
2133
 
                        window.scrollEnd = -1;
2134
 
                }
2135
 
                clearTimeout(window.scrollEnd);
2136
 
                window.scrollEnd = setTimeout(function() { YAHOO.widget.Overlay.windowScrollEvent.fire(); }, 1);
2137
 
        } else {
2138
 
                YAHOO.widget.Overlay.windowScrollEvent.fire();
2139
 
        }
2140
 
};
2141
 
 
2142
 
/**
2143
 
* The DOM event handler used to fire the CustomEvent for window resize
2144
 
* @method YAHOO.widget.Overlay.windowResizeHandler
2145
 
* @static
2146
 
* @param {DOMEvent} e The DOM resize event
2147
 
*/
2148
 
YAHOO.widget.Overlay.windowResizeHandler = function(e) {
2149
 
        if (YAHOO.widget.Module.prototype.browser == "ie" || YAHOO.widget.Module.prototype.browser == "ie7") {
2150
 
                if (! window.resizeEnd) {
2151
 
                        window.resizeEnd = -1;
2152
 
                }
2153
 
                clearTimeout(window.resizeEnd);
2154
 
                window.resizeEnd = setTimeout(function() { YAHOO.widget.Overlay.windowResizeEvent.fire(); }, 100);
2155
 
        } else {
2156
 
                YAHOO.widget.Overlay.windowResizeEvent.fire();
2157
 
        }
2158
 
};
2159
 
 
2160
 
/**
2161
 
* A boolean that indicated whether the window resize and scroll events have already been subscribed to.
2162
 
* @property YAHOO.widget.Overlay._initialized
2163
 
* @private
2164
 
* @type Boolean
2165
 
*/
2166
 
YAHOO.widget.Overlay._initialized = null;
2167
 
 
2168
 
if (YAHOO.widget.Overlay._initialized === null) {
2169
 
        YAHOO.util.Event.addListener(window, "scroll", YAHOO.widget.Overlay.windowScrollHandler);
2170
 
        YAHOO.util.Event.addListener(window, "resize", YAHOO.widget.Overlay.windowResizeHandler);
2171
 
 
2172
 
        YAHOO.widget.Overlay._initialized = true;
2173
 
}
2174
 
 
2175
 
/**
2176
 
* OverlayManager is used for maintaining the focus status of multiple Overlays.* @namespace YAHOO.widget
2177
 
* @namespace YAHOO.widget
2178
 
* @class OverlayManager
2179
 
* @constructor
2180
 
* @param {Array}        overlays        Optional. A collection of Overlays to register with the manager.
2181
 
* @param {Object}       userConfig              The object literal representing the user configuration of the OverlayManager
2182
 
*/
2183
 
YAHOO.widget.OverlayManager = function(userConfig) {
2184
 
        this.init(userConfig);
2185
 
};
2186
 
 
2187
 
/**
2188
 
* The CSS class representing a focused Overlay
2189
 
* @property YAHOO.widget.OverlayManager.CSS_FOCUSED
2190
 
* @static
2191
 
* @final
2192
 
* @type String
2193
 
*/
2194
 
YAHOO.widget.OverlayManager.CSS_FOCUSED = "focused";
2195
 
 
2196
 
YAHOO.widget.OverlayManager.prototype = {
2197
 
        /**
2198
 
        * The class's constructor function
2199
 
        * @property contructor
2200
 
        * @type Function
2201
 
        */
2202
 
        constructor : YAHOO.widget.OverlayManager,
2203
 
 
2204
 
        /**
2205
 
        * The array of Overlays that are currently registered
2206
 
        * @property overlays
2207
 
        * @type YAHOO.widget.Overlay[]
2208
 
        */
2209
 
        overlays : null,
2210
 
 
2211
 
        /**
2212
 
        * Initializes the default configuration of the OverlayManager
2213
 
        * @method initDefaultConfig
2214
 
        */      
2215
 
        initDefaultConfig : function() {
2216
 
                /**
2217
 
                * The collection of registered Overlays in use by the OverlayManager
2218
 
                * @config overlays
2219
 
                * @type YAHOO.widget.Overlay[]
2220
 
                * @default null
2221
 
                */
2222
 
                this.cfg.addProperty("overlays", { suppressEvent:true } );
2223
 
 
2224
 
                /**
2225
 
                * The default DOM event that should be used to focus an Overlay
2226
 
                * @config focusevent
2227
 
                * @type String
2228
 
                * @default "mousedown"
2229
 
                */
2230
 
                this.cfg.addProperty("focusevent", { value:"mousedown" } );
2231
 
        }, 
2232
 
 
2233
 
        /**
2234
 
        * Initializes the OverlayManager
2235
 
        * @method init
2236
 
        * @param {YAHOO.widget.Overlay[]}       overlays        Optional. A collection of Overlays to register with the manager.
2237
 
        * @param {Object}       userConfig              The object literal representing the user configuration of the OverlayManager
2238
 
        */
2239
 
        init : function(userConfig) {
2240
 
                /**
2241
 
                * The OverlayManager's Config object used for monitoring configuration properties.
2242
 
                * @property cfg
2243
 
                * @type YAHOO.util.Config
2244
 
                */
2245
 
                this.cfg = new YAHOO.util.Config(this);
2246
 
 
2247
 
                this.initDefaultConfig();
2248
 
 
2249
 
                if (userConfig) {
2250
 
                        this.cfg.applyConfig(userConfig, true);
2251
 
                }
2252
 
                this.cfg.fireQueue();
2253
 
 
2254
 
                /**
2255
 
                * The currently activated Overlay
2256
 
                * @property activeOverlay
2257
 
                * @private
2258
 
                * @type YAHOO.widget.Overlay
2259
 
                */
2260
 
                var activeOverlay = null;
2261
 
 
2262
 
                /**
2263
 
                * Returns the currently focused Overlay
2264
 
                * @method getActive
2265
 
                * @return {YAHOO.widget.Overlay}        The currently focused Overlay
2266
 
                */
2267
 
                this.getActive = function() {
2268
 
                        return activeOverlay;
2269
 
                };
2270
 
 
2271
 
                /**
2272
 
                * Focuses the specified Overlay
2273
 
                * @method focus
2274
 
                * @param {YAHOO.widget.Overlay} overlay The Overlay to focus
2275
 
                * @param {String} overlay       The id of the Overlay to focus
2276
 
                */
2277
 
                this.focus = function(overlay) {
2278
 
                        var o = this.find(overlay);
2279
 
                        if (o) {
2280
 
                                this.blurAll();
2281
 
                                activeOverlay = o;
2282
 
                                YAHOO.util.Dom.addClass(activeOverlay.element, YAHOO.widget.OverlayManager.CSS_FOCUSED);
2283
 
                                this.overlays.sort(this.compareZIndexDesc);
2284
 
                                var topZIndex = YAHOO.util.Dom.getStyle(this.overlays[0].element, "zIndex");
2285
 
                                if (! isNaN(topZIndex) && this.overlays[0] != overlay) {
2286
 
                                        activeOverlay.cfg.setProperty("zIndex", (parseInt(topZIndex, 10) + 2));
2287
 
                                }
2288
 
                                this.overlays.sort(this.compareZIndexDesc);
2289
 
                        }
2290
 
                };
2291
 
 
2292
 
                /**
2293
 
                * Removes the specified Overlay from the manager
2294
 
                * @method remove
2295
 
                * @param {YAHOO.widget.Overlay} overlay The Overlay to remove
2296
 
                * @param {String} overlay       The id of the Overlay to remove
2297
 
                */
2298
 
                this.remove = function(overlay) {
2299
 
                        var o = this.find(overlay);
2300
 
                        if (o) {
2301
 
                                var originalZ = YAHOO.util.Dom.getStyle(o.element, "zIndex");
2302
 
                                o.cfg.setProperty("zIndex", -1000, true);
2303
 
                                this.overlays.sort(this.compareZIndexDesc);
2304
 
                                this.overlays = this.overlays.slice(0, this.overlays.length-1);
2305
 
                                o.cfg.setProperty("zIndex", originalZ, true);
2306
 
 
2307
 
                                o.cfg.setProperty("manager", null);
2308
 
                                o.focusEvent = null;
2309
 
                                o.blurEvent = null;
2310
 
                                o.focus = null;
2311
 
                                o.blur = null;
2312
 
                        }
2313
 
                };
2314
 
 
2315
 
                /**
2316
 
                * Removes focus from all registered Overlays in the manager
2317
 
                * @method blurAll
2318
 
                */
2319
 
                this.blurAll = function() {
2320
 
                        activeOverlay = null;
2321
 
                        for (var o=0;o<this.overlays.length;o++) {
2322
 
                                YAHOO.util.Dom.removeClass(this.overlays[o].element, YAHOO.widget.OverlayManager.CSS_FOCUSED);
2323
 
                        }               
2324
 
                };
2325
 
 
2326
 
                var overlays = this.cfg.getProperty("overlays");
2327
 
                
2328
 
                if (! this.overlays) {
2329
 
                        this.overlays = [];
2330
 
                }
2331
 
 
2332
 
                if (overlays) {
2333
 
                        this.register(overlays);
2334
 
                        this.overlays.sort(this.compareZIndexDesc);
2335
 
                }
2336
 
        },
2337
 
 
2338
 
        /**
2339
 
        * Registers an Overlay or an array of Overlays with the manager. Upon registration, the Overlay receives functions for focus and blur, along with CustomEvents for each.
2340
 
        * @method register
2341
 
        * @param {YAHOO.widget.Overlay} overlay         An Overlay to register with the manager.
2342
 
        * @param {YAHOO.widget.Overlay[]}       overlay         An array of Overlays to register with the manager.
2343
 
        * @return       {Boolean}       True if any Overlays are registered.
2344
 
        */
2345
 
        register : function(overlay) {
2346
 
                if (overlay instanceof YAHOO.widget.Overlay) {
2347
 
                        overlay.cfg.addProperty("manager", { value:this } );
2348
 
 
2349
 
                        overlay.focusEvent = new YAHOO.util.CustomEvent("focus");
2350
 
                        overlay.blurEvent = new YAHOO.util.CustomEvent("blur");
2351
 
                        
2352
 
                        var mgr=this;
2353
 
 
2354
 
                        overlay.focus = function() {
2355
 
                                mgr.focus(this);
2356
 
                                this.focusEvent.fire();
2357
 
                        };
2358
 
 
2359
 
                        overlay.blur = function() {
2360
 
                                mgr.blurAll();
2361
 
                                this.blurEvent.fire();
2362
 
                        };
2363
 
 
2364
 
                        var focusOnDomEvent = function(e,obj) {
2365
 
                                overlay.focus();
2366
 
                        };
2367
 
                        
2368
 
                        var focusevent = this.cfg.getProperty("focusevent");
2369
 
                        YAHOO.util.Event.addListener(overlay.element,focusevent,focusOnDomEvent,this,true);
2370
 
 
2371
 
                        var zIndex = YAHOO.util.Dom.getStyle(overlay.element, "zIndex");
2372
 
                        if (! isNaN(zIndex)) {
2373
 
                                overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
2374
 
                        } else {
2375
 
                                overlay.cfg.setProperty("zIndex", 0);
2376
 
                        }
2377
 
                        
2378
 
                        this.overlays.push(overlay);
2379
 
                        return true;
2380
 
                } else if (overlay instanceof Array) {
2381
 
                        var regcount = 0;
2382
 
                        for (var i=0;i<overlay.length;i++) {
2383
 
                                if (this.register(overlay[i])) {
2384
 
                                        regcount++;
2385
 
                                }
2386
 
                        }
2387
 
                        if (regcount > 0) {
2388
 
                                return true;
2389
 
                        }
2390
 
                } else {
2391
 
                        return false;
2392
 
                }
2393
 
        },
2394
 
 
2395
 
        /**
2396
 
        * Attempts to locate an Overlay by instance or ID.
2397
 
        * @method find
2398
 
        * @param {YAHOO.widget.Overlay} overlay         An Overlay to locate within the manager
2399
 
        * @param {String}       overlay         An Overlay id to locate within the manager
2400
 
        * @return       {YAHOO.widget.Overlay}  The requested Overlay, if found, or null if it cannot be located.
2401
 
        */
2402
 
        find : function(overlay) {
2403
 
                if (overlay instanceof YAHOO.widget.Overlay) {
2404
 
                        for (var o=0;o<this.overlays.length;o++) {
2405
 
                                if (this.overlays[o] == overlay) {
2406
 
                                        return this.overlays[o];
2407
 
                                }
2408
 
                        }
2409
 
                } else if (typeof overlay == "string") {
2410
 
                        for (var p=0;p<this.overlays.length;p++) {
2411
 
                                if (this.overlays[p].id == overlay) {
2412
 
                                        return this.overlays[p];
2413
 
                                }
2414
 
                        }                       
2415
 
                }
2416
 
                return null;
2417
 
        },
2418
 
 
2419
 
        /**
2420
 
        * Used for sorting the manager's Overlays by z-index.
2421
 
        * @method compareZIndexDesc
2422
 
        * @private
2423
 
        * @return {Number}      0, 1, or -1, depending on where the Overlay should fall in the stacking order.
2424
 
        */
2425
 
        compareZIndexDesc : function(o1, o2) {
2426
 
                var zIndex1 = o1.cfg.getProperty("zIndex");
2427
 
                var zIndex2 = o2.cfg.getProperty("zIndex");
2428
 
 
2429
 
                if (zIndex1 > zIndex2) {
2430
 
                        return -1;
2431
 
                } else if (zIndex1 < zIndex2) {
2432
 
                        return 1;
2433
 
                } else {
2434
 
                        return 0;
2435
 
                }
2436
 
        },
2437
 
 
2438
 
        /**
2439
 
        * Shows all Overlays in the manager.
2440
 
        * @method showAll
2441
 
        */
2442
 
        showAll : function() {
2443
 
                for (var o=0;o<this.overlays.length;o++) {
2444
 
                        this.overlays[o].show();
2445
 
                }
2446
 
        },
2447
 
 
2448
 
        /**
2449
 
        * Hides all Overlays in the manager.
2450
 
        * @method hideAll
2451
 
        */
2452
 
        hideAll : function() {
2453
 
                for (var o=0;o<this.overlays.length;o++) {
2454
 
                        this.overlays[o].hide();
2455
 
                }
2456
 
        },
2457
 
 
2458
 
        /**
2459
 
        * Returns a string representation of the object.
2460
 
        * @method toString
2461
 
        * @return {String}      The string representation of the OverlayManager
2462
 
        */ 
2463
 
        toString : function() {
2464
 
                return "OverlayManager";
2465
 
        }
2466
 
 
2467
 
};
2468
 
 
2469
 
/**
2470
 
* KeyListener is a utility that provides an easy interface for listening for keydown/keyup events fired against DOM elements.
2471
 
* @namespace YAHOO.util
2472
 
* @class KeyListener
2473
 
* @constructor
2474
 
* @param {HTMLElement}  attachTo        The element or element ID to which the key event should be attached
2475
 
* @param {String}       attachTo        The element or element ID to which the key event should be attached
2476
 
* @param {Object}       keyData         The object literal representing the key(s) to detect. Possible attributes are shift(boolean), alt(boolean), ctrl(boolean) and keys(either an int or an array of ints representing keycodes).
2477
 
* @param {Function}     handler         The CustomEvent handler to fire when the key event is detected
2478
 
* @param {Object}       handler         An object literal representing the handler. 
2479
 
* @param {String}       event           Optional. The event (keydown or keyup) to listen for. Defaults automatically to keydown.
2480
 
*/
2481
 
YAHOO.util.KeyListener = function(attachTo, keyData, handler, event) {
2482
 
        if (! attachTo) {
2483
 
                YAHOO.log("No attachTo element specified", "error");
2484
 
        }
2485
 
        if (! keyData) {
2486
 
                YAHOO.log("No keyData specified", "error");
2487
 
        }
2488
 
        if (! handler) {
2489
 
                YAHOO.log("No handler specified", "error");
2490
 
        }
2491
 
 
2492
 
        if (! event) {
2493
 
                event = YAHOO.util.KeyListener.KEYDOWN;
2494
 
        }
2495
 
 
2496
 
        /**
2497
 
        * The CustomEvent fired internally when a key is pressed
2498
 
        * @event keyEvent
2499
 
        * @private
2500
 
        * @param {Object}       keyData         The object literal representing the key(s) to detect. Possible attributes are shift(boolean), alt(boolean), ctrl(boolean) and keys(either an int or an array of ints representing keycodes).
2501
 
        */
2502
 
        var keyEvent = new YAHOO.util.CustomEvent("keyPressed");
2503
 
        
2504
 
        /**
2505
 
        * The CustomEvent fired when the KeyListener is enabled via the enable() function
2506
 
        * @event enabledEvent
2507
 
        * @param {Object}       keyData         The object literal representing the key(s) to detect. Possible attributes are shift(boolean), alt(boolean), ctrl(boolean) and keys(either an int or an array of ints representing keycodes).
2508
 
        */
2509
 
        this.enabledEvent = new YAHOO.util.CustomEvent("enabled");
2510
 
 
2511
 
        /**
2512
 
        * The CustomEvent fired when the KeyListener is disabled via the disable() function
2513
 
        * @event disabledEvent
2514
 
        * @param {Object}       keyData         The object literal representing the key(s) to detect. Possible attributes are shift(boolean), alt(boolean), ctrl(boolean) and keys(either an int or an array of ints representing keycodes).
2515
 
        */
2516
 
        this.disabledEvent = new YAHOO.util.CustomEvent("disabled");
2517
 
 
2518
 
        if (typeof attachTo == 'string') {
2519
 
                attachTo = document.getElementById(attachTo);
2520
 
        }
2521
 
 
2522
 
        if (typeof handler == 'function') {
2523
 
                keyEvent.subscribe(handler);
2524
 
        } else {
2525
 
                keyEvent.subscribe(handler.fn, handler.scope, handler.correctScope);
2526
 
        }
2527
 
 
2528
 
        /**
2529
 
        * Handles the key event when a key is pressed.
2530
 
        * @method handleKeyPress
2531
 
        * @param {DOMEvent} e   The keypress DOM event
2532
 
        * @param {Object}       obj     The DOM event scope object
2533
 
        * @private
2534
 
        */
2535
 
        function handleKeyPress(e, obj) {
2536
 
                if (! keyData.shift) {  
2537
 
                        keyData.shift = false; 
2538
 
                }
2539
 
                if (! keyData.alt) {    
2540
 
                        keyData.alt = false;
2541
 
                }
2542
 
                if (! keyData.ctrl) {
2543
 
                        keyData.ctrl = false;
2544
 
                }
2545
 
 
2546
 
                // check held down modifying keys first
2547
 
                if (e.shiftKey == keyData.shift && 
2548
 
                        e.altKey   == keyData.alt &&
2549
 
                        e.ctrlKey  == keyData.ctrl) { // if we pass this, all modifiers match
2550
 
                        
2551
 
                        var dataItem;
2552
 
                        var keyPressed;
2553
 
 
2554
 
                        if (keyData.keys instanceof Array) {
2555
 
                                for (var i=0;i<keyData.keys.length;i++) {
2556
 
                                        dataItem = keyData.keys[i];
2557
 
 
2558
 
                                        if (dataItem == e.charCode ) {
2559
 
                                                keyEvent.fire(e.charCode, e);
2560
 
                                                break;
2561
 
                                        } else if (dataItem == e.keyCode) {
2562
 
                                                keyEvent.fire(e.keyCode, e);
2563
 
                                                break;
2564
 
                                        }
2565
 
                                }
2566
 
                        } else {
2567
 
                                dataItem = keyData.keys;
2568
 
                                if (dataItem == e.charCode ) {
2569
 
                                        keyEvent.fire(e.charCode, e);
2570
 
                                } else if (dataItem == e.keyCode) {
2571
 
                                        keyEvent.fire(e.keyCode, e);
2572
 
                                }
2573
 
                        }
2574
 
                }
2575
 
        }
2576
 
 
2577
 
        /**
2578
 
        * Enables the KeyListener by attaching the DOM event listeners to the target DOM element
2579
 
        * @method enable
2580
 
        */
2581
 
        this.enable = function() {
2582
 
                if (! this.enabled) {
2583
 
                        YAHOO.util.Event.addListener(attachTo, event, handleKeyPress);
2584
 
                        this.enabledEvent.fire(keyData);
2585
 
                }
2586
 
                /**
2587
 
                * Boolean indicating the enabled/disabled state of the Tooltip
2588
 
                * @property enabled
2589
 
                * @type Boolean
2590
 
                */
2591
 
                this.enabled = true;
2592
 
        };
2593
 
 
2594
 
        /**
2595
 
        * Disables the KeyListener by removing the DOM event listeners from the target DOM element
2596
 
        * @method disable
2597
 
        */
2598
 
        this.disable = function() {
2599
 
                if (this.enabled) {
2600
 
                        YAHOO.util.Event.removeListener(attachTo, event, handleKeyPress);
2601
 
                        this.disabledEvent.fire(keyData);
2602
 
                }
2603
 
                this.enabled = false;
2604
 
        };
2605
 
 
2606
 
        /**
2607
 
        * Returns a String representation of the object.
2608
 
        * @method toString
2609
 
        * @return {String}      The string representation of the KeyListener
2610
 
        */ 
2611
 
        this.toString = function() {
2612
 
                return "KeyListener [" + keyData.keys + "] " + attachTo.tagName + (attachTo.id ? "[" + attachTo.id + "]" : "");
2613
 
        };
2614
 
 
2615
 
};
2616
 
 
2617
 
/**
2618
 
* Constant representing the DOM "keydown" event.
2619
 
* @property YAHOO.util.KeyListener.KEYDOWN
2620
 
* @static
2621
 
* @final
2622
 
* @type String
2623
 
*/
2624
 
YAHOO.util.KeyListener.KEYDOWN = "keydown";
2625
 
 
2626
 
/**
2627
 
* Constant representing the DOM "keyup" event.
2628
 
* @property YAHOO.util.KeyListener.KEYUP
2629
 
* @static
2630
 
* @final
2631
 
* @type String
2632
 
*/
2633
 
YAHOO.util.KeyListener.KEYUP = "keyup";
2634
 
 
2635
 
/**
2636
 
* ContainerEffect encapsulates animation transitions that are executed when an Overlay is shown or hidden.
2637
 
* @namespace YAHOO.widget
2638
 
* @class ContainerEffect
2639
 
* @constructor
2640
 
* @param {YAHOO.widget.Overlay} overlay         The Overlay that the animation should be associated with
2641
 
* @param {Object}       attrIn          The object literal representing the animation arguments to be used for the animate-in transition. The arguments for this literal are: attributes(object, see YAHOO.util.Anim for description), duration(Number), and method(i.e. YAHOO.util.Easing.easeIn).
2642
 
* @param {Object}       attrOut         The object literal representing the animation arguments to be used for the animate-out transition. The arguments for this literal are: attributes(object, see YAHOO.util.Anim for description), duration(Number), and method(i.e. YAHOO.util.Easing.easeIn).
2643
 
* @param {HTMLElement}  targetElement   Optional. The target element that should be animated during the transition. Defaults to overlay.element.
2644
 
* @param {class}        Optional. The animation class to instantiate. Defaults to YAHOO.util.Anim. Other options include YAHOO.util.Motion.
2645
 
*/
2646
 
YAHOO.widget.ContainerEffect = function(overlay, attrIn, attrOut, targetElement, animClass) {
2647
 
        if (! animClass) {
2648
 
                animClass = YAHOO.util.Anim;
2649
 
        }
2650
 
 
2651
 
        /**
2652
 
        * The overlay to animate
2653
 
        * @property overlay
2654
 
        * @type YAHOO.widget.Overlay
2655
 
        */
2656
 
        this.overlay = overlay;
2657
 
        /**
2658
 
        * The animation attributes to use when transitioning into view
2659
 
        * @property attrIn
2660
 
        * @type Object
2661
 
        */
2662
 
        this.attrIn = attrIn;
2663
 
        /**
2664
 
        * The animation attributes to use when transitioning out of view
2665
 
        * @property attrOut
2666
 
        * @type Object
2667
 
        */
2668
 
        this.attrOut = attrOut;
2669
 
        /**
2670
 
        * The target element to be animated
2671
 
        * @property targetElement
2672
 
        * @type HTMLElement
2673
 
        */
2674
 
        this.targetElement = targetElement || overlay.element;
2675
 
        /**
2676
 
        * The animation class to use for animating the overlay
2677
 
        * @property animClass
2678
 
        * @type class
2679
 
        */
2680
 
        this.animClass = animClass;
2681
 
};
2682
 
 
2683
 
/**
2684
 
* Initializes the animation classes and events.
2685
 
* @method init
2686
 
*/
2687
 
YAHOO.widget.ContainerEffect.prototype.init = function() {
2688
 
        this.beforeAnimateInEvent = new YAHOO.util.CustomEvent("beforeAnimateIn");
2689
 
        this.beforeAnimateOutEvent = new YAHOO.util.CustomEvent("beforeAnimateOut");
2690
 
 
2691
 
        this.animateInCompleteEvent = new YAHOO.util.CustomEvent("animateInComplete");
2692
 
        this.animateOutCompleteEvent = new YAHOO.util.CustomEvent("animateOutComplete");
2693
 
 
2694
 
        this.animIn = new this.animClass(this.targetElement, this.attrIn.attributes, this.attrIn.duration, this.attrIn.method);
2695
 
        this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
2696
 
        this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
2697
 
        this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn, this);
2698
 
 
2699
 
        this.animOut = new this.animClass(this.targetElement, this.attrOut.attributes, this.attrOut.duration, this.attrOut.method);
2700
 
        this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
2701
 
        this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
2702
 
        this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut, this);
2703
 
};
2704
 
 
2705
 
/**
2706
 
* Triggers the in-animation.
2707
 
* @method animateIn
2708
 
*/
2709
 
YAHOO.widget.ContainerEffect.prototype.animateIn = function() {
2710
 
        this.beforeAnimateInEvent.fire();
2711
 
        this.animIn.animate();
2712
 
};
2713
 
 
2714
 
/**
2715
 
* Triggers the out-animation.
2716
 
* @method animateOut
2717
 
*/
2718
 
YAHOO.widget.ContainerEffect.prototype.animateOut = function() {
2719
 
        this.beforeAnimateOutEvent.fire();
2720
 
        this.animOut.animate();
2721
 
};
2722
 
 
2723
 
/**
2724
 
* The default onStart handler for the in-animation.
2725
 
* @method handleStartAnimateIn
2726
 
* @param {String} type  The CustomEvent type
2727
 
* @param {Object[]}     args    The CustomEvent arguments
2728
 
* @param {Object} obj   The scope object
2729
 
*/
2730
 
YAHOO.widget.ContainerEffect.prototype.handleStartAnimateIn = function(type, args, obj) { };
2731
 
/**
2732
 
* The default onTween handler for the in-animation.
2733
 
* @method handleTweenAnimateIn
2734
 
* @param {String} type  The CustomEvent type
2735
 
* @param {Object[]}     args    The CustomEvent arguments
2736
 
* @param {Object} obj   The scope object
2737
 
*/
2738
 
YAHOO.widget.ContainerEffect.prototype.handleTweenAnimateIn = function(type, args, obj) { };
2739
 
/**
2740
 
* The default onComplete handler for the in-animation.
2741
 
* @method handleCompleteAnimateIn
2742
 
* @param {String} type  The CustomEvent type
2743
 
* @param {Object[]}     args    The CustomEvent arguments
2744
 
* @param {Object} obj   The scope object
2745
 
*/
2746
 
YAHOO.widget.ContainerEffect.prototype.handleCompleteAnimateIn = function(type, args, obj) { };
2747
 
 
2748
 
/**
2749
 
* The default onStart handler for the out-animation.
2750
 
* @method handleStartAnimateOut
2751
 
* @param {String} type  The CustomEvent type
2752
 
* @param {Object[]}     args    The CustomEvent arguments
2753
 
* @param {Object} obj   The scope object
2754
 
*/
2755
 
YAHOO.widget.ContainerEffect.prototype.handleStartAnimateOut = function(type, args, obj) { };
2756
 
/**
2757
 
* The default onTween handler for the out-animation.
2758
 
* @method handleTweenAnimateOut
2759
 
* @param {String} type  The CustomEvent type
2760
 
* @param {Object[]}     args    The CustomEvent arguments
2761
 
* @param {Object} obj   The scope object
2762
 
*/
2763
 
YAHOO.widget.ContainerEffect.prototype.handleTweenAnimateOut = function(type, args, obj) { };
2764
 
/**
2765
 
* The default onComplete handler for the out-animation.
2766
 
* @method handleCompleteAnimateOut
2767
 
* @param {String} type  The CustomEvent type
2768
 
* @param {Object[]}     args    The CustomEvent arguments
2769
 
* @param {Object} obj   The scope object
2770
 
*/
2771
 
YAHOO.widget.ContainerEffect.prototype.handleCompleteAnimateOut = function(type, args, obj) { };
2772
 
 
2773
 
/**
2774
 
* Returns a string representation of the object.
2775
 
* @method toString
2776
 
* @return {String}      The string representation of the ContainerEffect
2777
 
*/ 
2778
 
YAHOO.widget.ContainerEffect.prototype.toString = function() {
2779
 
        var output = "ContainerEffect";
2780
 
        if (this.overlay) {
2781
 
                output += " [" + this.overlay.toString() + "]";
2782
 
        }
2783
 
        return output;
2784
 
};
2785
 
 
2786
 
/**
2787
 
* A pre-configured ContainerEffect instance that can be used for fading an overlay in and out.
2788
 
* @method FADE
2789
 
* @static
2790
 
* @param {Overlay}      overlay The Overlay object to animate
2791
 
* @param {Number}       dur     The duration of the animation
2792
 
* @return {ContainerEffect}     The configured ContainerEffect object
2793
 
*/
2794
 
YAHOO.widget.ContainerEffect.FADE = function(overlay, dur) {
2795
 
        var fade = new YAHOO.widget.ContainerEffect(overlay, { attributes:{opacity: {from:0, to:1}}, duration:dur, method:YAHOO.util.Easing.easeIn }, { attributes:{opacity: {to:0}}, duration:dur, method:YAHOO.util.Easing.easeOut}, overlay.element );
2796
 
 
2797
 
        fade.handleStartAnimateIn = function(type,args,obj) {
2798
 
                YAHOO.util.Dom.addClass(obj.overlay.element, "hide-select");
2799
 
                
2800
 
                if (! obj.overlay.underlay) {
2801
 
                        obj.overlay.cfg.refireEvent("underlay");
2802
 
                }
2803
 
 
2804
 
                if (obj.overlay.underlay) {
2805
 
                        obj.initialUnderlayOpacity = YAHOO.util.Dom.getStyle(obj.overlay.underlay, "opacity");
2806
 
                        obj.overlay.underlay.style.filter = null;
2807
 
                }
2808
 
 
2809
 
                YAHOO.util.Dom.setStyle(obj.overlay.element, "visibility", "visible"); 
2810
 
                YAHOO.util.Dom.setStyle(obj.overlay.element, "opacity", 0);
2811
 
        };
2812
 
 
2813
 
        fade.handleCompleteAnimateIn = function(type,args,obj) {
2814
 
                YAHOO.util.Dom.removeClass(obj.overlay.element, "hide-select");
2815
 
 
2816
 
                if (obj.overlay.element.style.filter) {
2817
 
                        obj.overlay.element.style.filter = null;
2818
 
                }                       
2819
 
                
2820
 
                if (obj.overlay.underlay) {
2821
 
                        YAHOO.util.Dom.setStyle(obj.overlay.underlay, "opacity", obj.initialUnderlayOpacity);
2822
 
                }
2823
 
 
2824
 
                obj.overlay.cfg.refireEvent("iframe");
2825
 
                obj.animateInCompleteEvent.fire();
2826
 
        };
2827
 
 
2828
 
        fade.handleStartAnimateOut = function(type, args, obj) {
2829
 
                YAHOO.util.Dom.addClass(obj.overlay.element, "hide-select");
2830
 
 
2831
 
                if (obj.overlay.underlay) {
2832
 
                        obj.overlay.underlay.style.filter = null;
2833
 
                }
2834
 
        };
2835
 
 
2836
 
        fade.handleCompleteAnimateOut =  function(type, args, obj) { 
2837
 
                YAHOO.util.Dom.removeClass(obj.overlay.element, "hide-select");
2838
 
                if (obj.overlay.element.style.filter) {
2839
 
                        obj.overlay.element.style.filter = null;
2840
 
                }                               
2841
 
                YAHOO.util.Dom.setStyle(obj.overlay.element, "visibility", "hidden");
2842
 
                YAHOO.util.Dom.setStyle(obj.overlay.element, "opacity", 1); 
2843
 
 
2844
 
                obj.overlay.cfg.refireEvent("iframe");
2845
 
 
2846
 
                obj.animateOutCompleteEvent.fire();
2847
 
        };      
2848
 
 
2849
 
        fade.init();
2850
 
        return fade;
2851
 
};
2852
 
 
2853
 
 
2854
 
/**
2855
 
* A pre-configured ContainerEffect instance that can be used for sliding an overlay in and out.
2856
 
* @method SLIDE
2857
 
* @static
2858
 
* @param {Overlay}      overlay The Overlay object to animate
2859
 
* @param {Number}       dur     The duration of the animation
2860
 
* @return {ContainerEffect}     The configured ContainerEffect object
2861
 
*/
2862
 
YAHOO.widget.ContainerEffect.SLIDE = function(overlay, dur) {
2863
 
        var x = overlay.cfg.getProperty("x") || YAHOO.util.Dom.getX(overlay.element);
2864
 
        var y = overlay.cfg.getProperty("y") || YAHOO.util.Dom.getY(overlay.element);
2865
 
 
2866
 
        var clientWidth = YAHOO.util.Dom.getClientWidth();
2867
 
        var offsetWidth = overlay.element.offsetWidth;
2868
 
 
2869
 
        var slide = new YAHOO.widget.ContainerEffect(overlay, { 
2870
 
                                                                                                                        attributes:{ points: { to:[x, y] } }, 
2871
 
                                                                                                                        duration:dur, 
2872
 
                                                                                                                        method:YAHOO.util.Easing.easeIn 
2873
 
                                                                                                                }, 
2874
 
                                                                                                                { 
2875
 
                                                                                                                        attributes:{ points: { to:[(clientWidth+25), y] } },
2876
 
                                                                                                                        duration:dur, 
2877
 
                                                                                                                        method:YAHOO.util.Easing.easeOut
2878
 
                                                                                                                },
2879
 
                                                                                                                overlay.element,
2880
 
                                                                                                                YAHOO.util.Motion);
2881
 
                                                                                                
2882
 
 
2883
 
        slide.handleStartAnimateIn = function(type,args,obj) {
2884
 
                obj.overlay.element.style.left = (-25-offsetWidth) + "px";
2885
 
                obj.overlay.element.style.top  = y + "px";
2886
 
        };
2887
 
        
2888
 
        slide.handleTweenAnimateIn = function(type, args, obj) {
2889
 
 
2890
 
 
2891
 
                var pos = YAHOO.util.Dom.getXY(obj.overlay.element);
2892
 
 
2893
 
                var currentX = pos[0];
2894
 
                var currentY = pos[1];
2895
 
 
2896
 
                if (YAHOO.util.Dom.getStyle(obj.overlay.element, "visibility") == "hidden" && currentX < x) {
2897
 
                        YAHOO.util.Dom.setStyle(obj.overlay.element, "visibility", "visible");
2898
 
                }
2899
 
 
2900
 
                obj.overlay.cfg.setProperty("xy", [currentX,currentY], true);
2901
 
                obj.overlay.cfg.refireEvent("iframe");
2902
 
        };
2903
 
        
2904
 
        slide.handleCompleteAnimateIn = function(type, args, obj) {
2905
 
                obj.overlay.cfg.setProperty("xy", [x,y], true);
2906
 
                obj.startX = x;
2907
 
                obj.startY = y;
2908
 
                obj.overlay.cfg.refireEvent("iframe");
2909
 
                obj.animateInCompleteEvent.fire();
2910
 
        };
2911
 
 
2912
 
        slide.handleStartAnimateOut = function(type, args, obj) {
2913
 
                var vw = YAHOO.util.Dom.getViewportWidth();
2914
 
                
2915
 
                var pos = YAHOO.util.Dom.getXY(obj.overlay.element);
2916
 
 
2917
 
                var yso = pos[1];
2918
 
 
2919
 
                var currentTo = obj.animOut.attributes.points.to;
2920
 
                obj.animOut.attributes.points.to = [(vw+25), yso];
2921
 
        };
2922
 
 
2923
 
        slide.handleTweenAnimateOut = function(type, args, obj) {
2924
 
                var pos = YAHOO.util.Dom.getXY(obj.overlay.element);
2925
 
 
2926
 
                var xto = pos[0];
2927
 
                var yto = pos[1];
2928
 
 
2929
 
                obj.overlay.cfg.setProperty("xy", [xto,yto], true);
2930
 
                obj.overlay.cfg.refireEvent("iframe");
2931
 
        };
2932
 
 
2933
 
        slide.handleCompleteAnimateOut = function(type, args, obj) { 
2934
 
                YAHOO.util.Dom.setStyle(obj.overlay.element, "visibility", "hidden");
2935
 
 
2936
 
                obj.overlay.cfg.setProperty("xy", [x,y]);
2937
 
                obj.animateOutCompleteEvent.fire();
2938
 
        };      
2939
 
 
2940
 
        slide.init();
2941
 
        return slide;
2942
 
};
 
 
b'\\ No newline at end of file'
 
5
version: 2.6.0
 
6
*/
 
7
(function () {
 
8
 
 
9
    /**
 
10
    * Config is a utility used within an Object to allow the implementer to
 
11
    * maintain a list of local configuration properties and listen for changes 
 
12
    * to those properties dynamically using CustomEvent. The initial values are 
 
13
    * also maintained so that the configuration can be reset at any given point 
 
14
    * to its initial state.
 
15
    * @namespace YAHOO.util
 
16
    * @class Config
 
17
    * @constructor
 
18
    * @param {Object} owner The owner Object to which this Config Object belongs
 
19
    */
 
20
    YAHOO.util.Config = function (owner) {
 
21
 
 
22
        if (owner) {
 
23
            this.init(owner);
 
24
        }
 
25
 
 
26
        if (!owner) {  YAHOO.log("No owner specified for Config object", "error", "Config"); }
 
27
 
 
28
    };
 
29
 
 
30
 
 
31
    var Lang = YAHOO.lang,
 
32
        CustomEvent = YAHOO.util.CustomEvent,
 
33
        Config = YAHOO.util.Config;
 
34
 
 
35
 
 
36
    /**
 
37
     * Constant representing the CustomEvent type for the config changed event.
 
38
     * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
 
39
     * @private
 
40
     * @static
 
41
     * @final
 
42
     */
 
43
    Config.CONFIG_CHANGED_EVENT = "configChanged";
 
44
    
 
45
    /**
 
46
     * Constant representing the boolean type string
 
47
     * @property YAHOO.util.Config.BOOLEAN_TYPE
 
48
     * @private
 
49
     * @static
 
50
     * @final
 
51
     */
 
52
    Config.BOOLEAN_TYPE = "boolean";
 
53
    
 
54
    Config.prototype = {
 
55
     
 
56
        /**
 
57
        * Object reference to the owner of this Config Object
 
58
        * @property owner
 
59
        * @type Object
 
60
        */
 
61
        owner: null,
 
62
        
 
63
        /**
 
64
        * Boolean flag that specifies whether a queue is currently 
 
65
        * being executed
 
66
        * @property queueInProgress
 
67
        * @type Boolean
 
68
        */
 
69
        queueInProgress: false,
 
70
        
 
71
        /**
 
72
        * Maintains the local collection of configuration property objects and 
 
73
        * their specified values
 
74
        * @property config
 
75
        * @private
 
76
        * @type Object
 
77
        */ 
 
78
        config: null,
 
79
        
 
80
        /**
 
81
        * Maintains the local collection of configuration property objects as 
 
82
        * they were initially applied.
 
83
        * This object is used when resetting a property.
 
84
        * @property initialConfig
 
85
        * @private
 
86
        * @type Object
 
87
        */ 
 
88
        initialConfig: null,
 
89
        
 
90
        /**
 
91
        * Maintains the local, normalized CustomEvent queue
 
92
        * @property eventQueue
 
93
        * @private
 
94
        * @type Object
 
95
        */ 
 
96
        eventQueue: null,
 
97
        
 
98
        /**
 
99
        * Custom Event, notifying subscribers when Config properties are set 
 
100
        * (setProperty is called without the silent flag
 
101
        * @event configChangedEvent
 
102
        */
 
103
        configChangedEvent: null,
 
104
    
 
105
        /**
 
106
        * Initializes the configuration Object and all of its local members.
 
107
        * @method init
 
108
        * @param {Object} owner The owner Object to which this Config 
 
109
        * Object belongs
 
110
        */
 
111
        init: function (owner) {
 
112
    
 
113
            this.owner = owner;
 
114
    
 
115
            this.configChangedEvent = 
 
116
                this.createEvent(Config.CONFIG_CHANGED_EVENT);
 
117
    
 
118
            this.configChangedEvent.signature = CustomEvent.LIST;
 
119
            this.queueInProgress = false;
 
120
            this.config = {};
 
121
            this.initialConfig = {};
 
122
            this.eventQueue = [];
 
123
        
 
124
        },
 
125
        
 
126
        /**
 
127
        * Validates that the value passed in is a Boolean.
 
128
        * @method checkBoolean
 
129
        * @param {Object} val The value to validate
 
130
        * @return {Boolean} true, if the value is valid
 
131
        */ 
 
132
        checkBoolean: function (val) {
 
133
            return (typeof val == Config.BOOLEAN_TYPE);
 
134
        },
 
135
        
 
136
        /**
 
137
        * Validates that the value passed in is a number.
 
138
        * @method checkNumber
 
139
        * @param {Object} val The value to validate
 
140
        * @return {Boolean} true, if the value is valid
 
141
        */
 
142
        checkNumber: function (val) {
 
143
            return (!isNaN(val));
 
144
        },
 
145
        
 
146
        /**
 
147
        * Fires a configuration property event using the specified value. 
 
148
        * @method fireEvent
 
149
        * @private
 
150
        * @param {String} key The configuration property's name
 
151
        * @param {value} Object The value of the correct type for the property
 
152
        */ 
 
153
        fireEvent: function ( key, value ) {
 
154
            YAHOO.log("Firing Config event: " + key + "=" + value, "info", "Config");
 
155
            var property = this.config[key];
 
156
        
 
157
            if (property && property.event) {
 
158
                property.event.fire(value);
 
159
            } 
 
160
        },
 
161
        
 
162
        /**
 
163
        * Adds a property to the Config Object's private config hash.
 
164
        * @method addProperty
 
165
        * @param {String} key The configuration property's name
 
166
        * @param {Object} propertyObject The Object containing all of this 
 
167
        * property's arguments
 
168
        */
 
169
        addProperty: function ( key, propertyObject ) {
 
170
            key = key.toLowerCase();
 
171
            YAHOO.log("Added property: " + key, "info", "Config");
 
172
        
 
173
            this.config[key] = propertyObject;
 
174
        
 
175
            propertyObject.event = this.createEvent(key, { scope: this.owner });
 
176
            propertyObject.event.signature = CustomEvent.LIST;
 
177
            
 
178
            
 
179
            propertyObject.key = key;
 
180
        
 
181
            if (propertyObject.handler) {
 
182
                propertyObject.event.subscribe(propertyObject.handler, 
 
183
                    this.owner);
 
184
            }
 
185
        
 
186
            this.setProperty(key, propertyObject.value, true);
 
187
            
 
188
            if (! propertyObject.suppressEvent) {
 
189
                this.queueProperty(key, propertyObject.value);
 
190
            }
 
191
            
 
192
        },
 
193
        
 
194
        /**
 
195
        * Returns a key-value configuration map of the values currently set in  
 
196
        * the Config Object.
 
197
        * @method getConfig
 
198
        * @return {Object} The current config, represented in a key-value map
 
199
        */
 
200
        getConfig: function () {
 
201
        
 
202
            var cfg = {},
 
203
                currCfg = this.config,
 
204
                prop,
 
205
                property;
 
206
                
 
207
            for (prop in currCfg) {
 
208
                if (Lang.hasOwnProperty(currCfg, prop)) {
 
209
                    property = currCfg[prop];
 
210
                    if (property && property.event) {
 
211
                        cfg[prop] = property.value;
 
212
                    }
 
213
                }
 
214
            }
 
215
 
 
216
            return cfg;
 
217
        },
 
218
        
 
219
        /**
 
220
        * Returns the value of specified property.
 
221
        * @method getProperty
 
222
        * @param {String} key The name of the property
 
223
        * @return {Object}  The value of the specified property
 
224
        */
 
225
        getProperty: function (key) {
 
226
            var property = this.config[key.toLowerCase()];
 
227
            if (property && property.event) {
 
228
                return property.value;
 
229
            } else {
 
230
                return undefined;
 
231
            }
 
232
        },
 
233
        
 
234
        /**
 
235
        * Resets the specified property's value to its initial value.
 
236
        * @method resetProperty
 
237
        * @param {String} key The name of the property
 
238
        * @return {Boolean} True is the property was reset, false if not
 
239
        */
 
240
        resetProperty: function (key) {
 
241
    
 
242
            key = key.toLowerCase();
 
243
        
 
244
            var property = this.config[key];
 
245
    
 
246
            if (property && property.event) {
 
247
    
 
248
                if (this.initialConfig[key] && 
 
249
                    !Lang.isUndefined(this.initialConfig[key])) {
 
250
    
 
251
                    this.setProperty(key, this.initialConfig[key]);
 
252
 
 
253
                    return true;
 
254
    
 
255
                }
 
256
    
 
257
            } else {
 
258
    
 
259
                return false;
 
260
            }
 
261
    
 
262
        },
 
263
        
 
264
        /**
 
265
        * Sets the value of a property. If the silent property is passed as 
 
266
        * true, the property's event will not be fired.
 
267
        * @method setProperty
 
268
        * @param {String} key The name of the property
 
269
        * @param {String} value The value to set the property to
 
270
        * @param {Boolean} silent Whether the value should be set silently, 
 
271
        * without firing the property event.
 
272
        * @return {Boolean} True, if the set was successful, false if it failed.
 
273
        */
 
274
        setProperty: function (key, value, silent) {
 
275
        
 
276
            var property;
 
277
        
 
278
            key = key.toLowerCase();
 
279
            YAHOO.log("setProperty: " + key + "=" + value, "info", "Config");
 
280
        
 
281
            if (this.queueInProgress && ! silent) {
 
282
                // Currently running through a queue... 
 
283
                this.queueProperty(key,value);
 
284
                return true;
 
285
    
 
286
            } else {
 
287
                property = this.config[key];
 
288
                if (property && property.event) {
 
289
                    if (property.validator && !property.validator(value)) {
 
290
                        return false;
 
291
                    } else {
 
292
                        property.value = value;
 
293
                        if (! silent) {
 
294
                            this.fireEvent(key, value);
 
295
                            this.configChangedEvent.fire([key, value]);
 
296
                        }
 
297
                        return true;
 
298
                    }
 
299
                } else {
 
300
                    return false;
 
301
                }
 
302
            }
 
303
        },
 
304
        
 
305
        /**
 
306
        * Sets the value of a property and queues its event to execute. If the 
 
307
        * event is already scheduled to execute, it is
 
308
        * moved from its current position to the end of the queue.
 
309
        * @method queueProperty
 
310
        * @param {String} key The name of the property
 
311
        * @param {String} value The value to set the property to
 
312
        * @return {Boolean}  true, if the set was successful, false if 
 
313
        * it failed.
 
314
        */ 
 
315
        queueProperty: function (key, value) {
 
316
        
 
317
            key = key.toLowerCase();
 
318
            YAHOO.log("queueProperty: " + key + "=" + value, "info", "Config");
 
319
        
 
320
            var property = this.config[key],
 
321
                foundDuplicate = false,
 
322
                iLen,
 
323
                queueItem,
 
324
                queueItemKey,
 
325
                queueItemValue,
 
326
                sLen,
 
327
                supercedesCheck,
 
328
                qLen,
 
329
                queueItemCheck,
 
330
                queueItemCheckKey,
 
331
                queueItemCheckValue,
 
332
                i,
 
333
                s,
 
334
                q;
 
335
                                
 
336
            if (property && property.event) {
 
337
    
 
338
                if (!Lang.isUndefined(value) && property.validator && 
 
339
                    !property.validator(value)) { // validator
 
340
                    return false;
 
341
                } else {
 
342
        
 
343
                    if (!Lang.isUndefined(value)) {
 
344
                        property.value = value;
 
345
                    } else {
 
346
                        value = property.value;
 
347
                    }
 
348
        
 
349
                    foundDuplicate = false;
 
350
                    iLen = this.eventQueue.length;
 
351
        
 
352
                    for (i = 0; i < iLen; i++) {
 
353
                        queueItem = this.eventQueue[i];
 
354
        
 
355
                        if (queueItem) {
 
356
                            queueItemKey = queueItem[0];
 
357
                            queueItemValue = queueItem[1];
 
358
 
 
359
                            if (queueItemKey == key) {
 
360
    
 
361
                                /*
 
362
                                    found a dupe... push to end of queue, null 
 
363
                                    current item, and break
 
364
                                */
 
365
    
 
366
                                this.eventQueue[i] = null;
 
367
    
 
368
                                this.eventQueue.push(
 
369
                                    [key, (!Lang.isUndefined(value) ? 
 
370
                                    value : queueItemValue)]);
 
371
    
 
372
                                foundDuplicate = true;
 
373
                                break;
 
374
                            }
 
375
                        }
 
376
                    }
 
377
                    
 
378
                    // this is a refire, or a new property in the queue
 
379
    
 
380
                    if (! foundDuplicate && !Lang.isUndefined(value)) { 
 
381
                        this.eventQueue.push([key, value]);
 
382
                    }
 
383
                }
 
384
        
 
385
                if (property.supercedes) {
 
386
 
 
387
                    sLen = property.supercedes.length;
 
388
 
 
389
                    for (s = 0; s < sLen; s++) {
 
390
 
 
391
                        supercedesCheck = property.supercedes[s];
 
392
                        qLen = this.eventQueue.length;
 
393
 
 
394
                        for (q = 0; q < qLen; q++) {
 
395
                            queueItemCheck = this.eventQueue[q];
 
396
 
 
397
                            if (queueItemCheck) {
 
398
                                queueItemCheckKey = queueItemCheck[0];
 
399
                                queueItemCheckValue = queueItemCheck[1];
 
400
 
 
401
                                if (queueItemCheckKey == 
 
402
                                    supercedesCheck.toLowerCase() ) {
 
403
 
 
404
                                    this.eventQueue.push([queueItemCheckKey, 
 
405
                                        queueItemCheckValue]);
 
406
 
 
407
                                    this.eventQueue[q] = null;
 
408
                                    break;
 
409
 
 
410
                                }
 
411
                            }
 
412
                        }
 
413
                    }
 
414
                }
 
415
 
 
416
                YAHOO.log("Config event queue: " + this.outputEventQueue(), "info", "Config");
 
417
 
 
418
                return true;
 
419
            } else {
 
420
                return false;
 
421
            }
 
422
        },
 
423
        
 
424
        /**
 
425
        * Fires the event for a property using the property's current value.
 
426
        * @method refireEvent
 
427
        * @param {String} key The name of the property
 
428
        */
 
429
        refireEvent: function (key) {
 
430
    
 
431
            key = key.toLowerCase();
 
432
        
 
433
            var property = this.config[key];
 
434
    
 
435
            if (property && property.event && 
 
436
    
 
437
                !Lang.isUndefined(property.value)) {
 
438
    
 
439
                if (this.queueInProgress) {
 
440
    
 
441
                    this.queueProperty(key);
 
442
    
 
443
                } else {
 
444
    
 
445
                    this.fireEvent(key, property.value);
 
446
    
 
447
                }
 
448
    
 
449
            }
 
450
        },
 
451
        
 
452
        /**
 
453
        * Applies a key-value Object literal to the configuration, replacing  
 
454
        * any existing values, and queueing the property events.
 
455
        * Although the values will be set, fireQueue() must be called for their 
 
456
        * associated events to execute.
 
457
        * @method applyConfig
 
458
        * @param {Object} userConfig The configuration Object literal
 
459
        * @param {Boolean} init  When set to true, the initialConfig will 
 
460
        * be set to the userConfig passed in, so that calling a reset will 
 
461
        * reset the properties to the passed values.
 
462
        */
 
463
        applyConfig: function (userConfig, init) {
 
464
        
 
465
            var sKey,
 
466
                oConfig;
 
467
 
 
468
            if (init) {
 
469
                oConfig = {};
 
470
                for (sKey in userConfig) {
 
471
                    if (Lang.hasOwnProperty(userConfig, sKey)) {
 
472
                        oConfig[sKey.toLowerCase()] = userConfig[sKey];
 
473
                    }
 
474
                }
 
475
                this.initialConfig = oConfig;
 
476
            }
 
477
 
 
478
            for (sKey in userConfig) {
 
479
                if (Lang.hasOwnProperty(userConfig, sKey)) {
 
480
                    this.queueProperty(sKey, userConfig[sKey]);
 
481
                }
 
482
            }
 
483
        },
 
484
        
 
485
        /**
 
486
        * Refires the events for all configuration properties using their 
 
487
        * current values.
 
488
        * @method refresh
 
489
        */
 
490
        refresh: function () {
 
491
 
 
492
            var prop;
 
493
 
 
494
            for (prop in this.config) {
 
495
                if (Lang.hasOwnProperty(this.config, prop)) {
 
496
                    this.refireEvent(prop);
 
497
                }
 
498
            }
 
499
        },
 
500
        
 
501
        /**
 
502
        * Fires the normalized list of queued property change events
 
503
        * @method fireQueue
 
504
        */
 
505
        fireQueue: function () {
 
506
        
 
507
            var i, 
 
508
                queueItem,
 
509
                key,
 
510
                value,
 
511
                property;
 
512
        
 
513
            this.queueInProgress = true;
 
514
            for (i = 0;i < this.eventQueue.length; i++) {
 
515
                queueItem = this.eventQueue[i];
 
516
                if (queueItem) {
 
517
        
 
518
                    key = queueItem[0];
 
519
                    value = queueItem[1];
 
520
                    property = this.config[key];
 
521
 
 
522
                    property.value = value;
 
523
 
 
524
                    // Clear out queue entry, to avoid it being 
 
525
                    // re-added to the queue by any queueProperty/supercedes
 
526
                    // calls which are invoked during fireEvent
 
527
                    this.eventQueue[i] = null;
 
528
 
 
529
                    this.fireEvent(key,value);
 
530
                }
 
531
            }
 
532
            
 
533
            this.queueInProgress = false;
 
534
            this.eventQueue = [];
 
535
        },
 
536
        
 
537
        /**
 
538
        * Subscribes an external handler to the change event for any 
 
539
        * given property. 
 
540
        * @method subscribeToConfigEvent
 
541
        * @param {String} key The property name
 
542
        * @param {Function} handler The handler function to use subscribe to 
 
543
        * the property's event
 
544
        * @param {Object} obj The Object to use for scoping the event handler 
 
545
        * (see CustomEvent documentation)
 
546
        * @param {Boolean} override Optional. If true, will override "this"  
 
547
        * within the handler to map to the scope Object passed into the method.
 
548
        * @return {Boolean} True, if the subscription was successful, 
 
549
        * otherwise false.
 
550
        */ 
 
551
        subscribeToConfigEvent: function (key, handler, obj, override) {
 
552
    
 
553
            var property = this.config[key.toLowerCase()];
 
554
    
 
555
            if (property && property.event) {
 
556
                if (!Config.alreadySubscribed(property.event, handler, obj)) {
 
557
                    property.event.subscribe(handler, obj, override);
 
558
                }
 
559
                return true;
 
560
            } else {
 
561
                return false;
 
562
            }
 
563
    
 
564
        },
 
565
        
 
566
        /**
 
567
        * Unsubscribes an external handler from the change event for any 
 
568
        * given property. 
 
569
        * @method unsubscribeFromConfigEvent
 
570
        * @param {String} key The property name
 
571
        * @param {Function} handler The handler function to use subscribe to 
 
572
        * the property's event
 
573
        * @param {Object} obj The Object to use for scoping the event 
 
574
        * handler (see CustomEvent documentation)
 
575
        * @return {Boolean} True, if the unsubscription was successful, 
 
576
        * otherwise false.
 
577
        */
 
578
        unsubscribeFromConfigEvent: function (key, handler, obj) {
 
579
            var property = this.config[key.toLowerCase()];
 
580
            if (property && property.event) {
 
581
                return property.event.unsubscribe(handler, obj);
 
582
            } else {
 
583
                return false;
 
584
            }
 
585
        },
 
586
        
 
587
        /**
 
588
        * Returns a string representation of the Config object
 
589
        * @method toString
 
590
        * @return {String} The Config object in string format.
 
591
        */
 
592
        toString: function () {
 
593
            var output = "Config";
 
594
            if (this.owner) {
 
595
                output += " [" + this.owner.toString() + "]";
 
596
            }
 
597
            return output;
 
598
        },
 
599
        
 
600
        /**
 
601
        * Returns a string representation of the Config object's current 
 
602
        * CustomEvent queue
 
603
        * @method outputEventQueue
 
604
        * @return {String} The string list of CustomEvents currently queued 
 
605
        * for execution
 
606
        */
 
607
        outputEventQueue: function () {
 
608
 
 
609
            var output = "",
 
610
                queueItem,
 
611
                q,
 
612
                nQueue = this.eventQueue.length;
 
613
              
 
614
            for (q = 0; q < nQueue; q++) {
 
615
                queueItem = this.eventQueue[q];
 
616
                if (queueItem) {
 
617
                    output += queueItem[0] + "=" + queueItem[1] + ", ";
 
618
                }
 
619
            }
 
620
            return output;
 
621
        },
 
622
 
 
623
        /**
 
624
        * Sets all properties to null, unsubscribes all listeners from each 
 
625
        * property's change event and all listeners from the configChangedEvent.
 
626
        * @method destroy
 
627
        */
 
628
        destroy: function () {
 
629
 
 
630
            var oConfig = this.config,
 
631
                sProperty,
 
632
                oProperty;
 
633
 
 
634
 
 
635
            for (sProperty in oConfig) {
 
636
            
 
637
                if (Lang.hasOwnProperty(oConfig, sProperty)) {
 
638
 
 
639
                    oProperty = oConfig[sProperty];
 
640
 
 
641
                    oProperty.event.unsubscribeAll();
 
642
                    oProperty.event = null;
 
643
 
 
644
                }
 
645
            
 
646
            }
 
647
            
 
648
            this.configChangedEvent.unsubscribeAll();
 
649
            
 
650
            this.configChangedEvent = null;
 
651
            this.owner = null;
 
652
            this.config = null;
 
653
            this.initialConfig = null;
 
654
            this.eventQueue = null;
 
655
        
 
656
        }
 
657
 
 
658
    };
 
659
    
 
660
    
 
661
    
 
662
    /**
 
663
    * Checks to determine if a particular function/Object pair are already 
 
664
    * subscribed to the specified CustomEvent
 
665
    * @method YAHOO.util.Config.alreadySubscribed
 
666
    * @static
 
667
    * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check 
 
668
    * the subscriptions
 
669
    * @param {Function} fn The function to look for in the subscribers list
 
670
    * @param {Object} obj The execution scope Object for the subscription
 
671
    * @return {Boolean} true, if the function/Object pair is already subscribed 
 
672
    * to the CustomEvent passed in
 
673
    */
 
674
    Config.alreadySubscribed = function (evt, fn, obj) {
 
675
    
 
676
        var nSubscribers = evt.subscribers.length,
 
677
            subsc,
 
678
            i;
 
679
 
 
680
        if (nSubscribers > 0) {
 
681
            i = nSubscribers - 1;
 
682
            do {
 
683
                subsc = evt.subscribers[i];
 
684
                if (subsc && subsc.obj == obj && subsc.fn == fn) {
 
685
                    return true;
 
686
                }
 
687
            }
 
688
            while (i--);
 
689
        }
 
690
 
 
691
        return false;
 
692
 
 
693
    };
 
694
 
 
695
    YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
 
696
 
 
697
}());
 
698
 
 
699
(function () {
 
700
 
 
701
    /**
 
702
    * The Container family of components is designed to enable developers to 
 
703
    * create different kinds of content-containing modules on the web. Module 
 
704
    * and Overlay are the most basic containers, and they can be used directly 
 
705
    * or extended to build custom containers. Also part of the Container family 
 
706
    * are four UI controls that extend Module and Overlay: Tooltip, Panel, 
 
707
    * Dialog, and SimpleDialog.
 
708
    * @module container
 
709
    * @title Container
 
710
    * @requires yahoo, dom, event 
 
711
    * @optional dragdrop, animation, button
 
712
    */
 
713
    
 
714
    /**
 
715
    * Module is a JavaScript representation of the Standard Module Format. 
 
716
    * Standard Module Format is a simple standard for markup containers where 
 
717
    * child nodes representing the header, body, and footer of the content are 
 
718
    * denoted using the CSS classes "hd", "bd", and "ft" respectively. 
 
719
    * Module is the base class for all other classes in the YUI 
 
720
    * Container package.
 
721
    * @namespace YAHOO.widget
 
722
    * @class Module
 
723
    * @constructor
 
724
    * @param {String} el The element ID representing the Module <em>OR</em>
 
725
    * @param {HTMLElement} el The element representing the Module
 
726
    * @param {Object} userConfig The configuration Object literal containing 
 
727
    * the configuration that should be set for this module. See configuration 
 
728
    * documentation for more details.
 
729
    */
 
730
    YAHOO.widget.Module = function (el, userConfig) {
 
731
        if (el) {
 
732
            this.init(el, userConfig);
 
733
        } else {
 
734
            YAHOO.log("No element or element ID specified" + 
 
735
                " for Module instantiation", "error");
 
736
        }
 
737
    };
 
738
 
 
739
    var Dom = YAHOO.util.Dom,
 
740
        Config = YAHOO.util.Config,
 
741
        Event = YAHOO.util.Event,
 
742
        CustomEvent = YAHOO.util.CustomEvent,
 
743
        Module = YAHOO.widget.Module,
 
744
 
 
745
        m_oModuleTemplate,
 
746
        m_oHeaderTemplate,
 
747
        m_oBodyTemplate,
 
748
        m_oFooterTemplate,
 
749
 
 
750
        /**
 
751
        * Constant representing the name of the Module's events
 
752
        * @property EVENT_TYPES
 
753
        * @private
 
754
        * @final
 
755
        * @type Object
 
756
        */
 
757
        EVENT_TYPES = {
 
758
            "BEFORE_INIT": "beforeInit",
 
759
            "INIT": "init",
 
760
            "APPEND": "append",
 
761
            "BEFORE_RENDER": "beforeRender",
 
762
            "RENDER": "render",
 
763
            "CHANGE_HEADER": "changeHeader",
 
764
            "CHANGE_BODY": "changeBody",
 
765
            "CHANGE_FOOTER": "changeFooter",
 
766
            "CHANGE_CONTENT": "changeContent",
 
767
            "DESTORY": "destroy",
 
768
            "BEFORE_SHOW": "beforeShow",
 
769
            "SHOW": "show",
 
770
            "BEFORE_HIDE": "beforeHide",
 
771
            "HIDE": "hide"
 
772
        },
 
773
            
 
774
        /**
 
775
        * Constant representing the Module's configuration properties
 
776
        * @property DEFAULT_CONFIG
 
777
        * @private
 
778
        * @final
 
779
        * @type Object
 
780
        */
 
781
        DEFAULT_CONFIG = {
 
782
        
 
783
            "VISIBLE": { 
 
784
                key: "visible", 
 
785
                value: true, 
 
786
                validator: YAHOO.lang.isBoolean 
 
787
            },
 
788
        
 
789
            "EFFECT": { 
 
790
                key: "effect", 
 
791
                suppressEvent: true, 
 
792
                supercedes: ["visible"] 
 
793
            },
 
794
 
 
795
            "MONITOR_RESIZE": { 
 
796
                key: "monitorresize", 
 
797
                value: true  
 
798
            },
 
799
 
 
800
            "APPEND_TO_DOCUMENT_BODY": { 
 
801
                key: "appendtodocumentbody", 
 
802
                value: false
 
803
            }
 
804
        };
 
805
    
 
806
    /**
 
807
    * Constant representing the prefix path to use for non-secure images
 
808
    * @property YAHOO.widget.Module.IMG_ROOT
 
809
    * @static
 
810
    * @final
 
811
    * @type String
 
812
    */
 
813
    Module.IMG_ROOT = null;
 
814
    
 
815
    /**
 
816
    * Constant representing the prefix path to use for securely served images
 
817
    * @property YAHOO.widget.Module.IMG_ROOT_SSL
 
818
    * @static
 
819
    * @final
 
820
    * @type String
 
821
    */
 
822
    Module.IMG_ROOT_SSL = null;
 
823
    
 
824
    /**
 
825
    * Constant for the default CSS class name that represents a Module
 
826
    * @property YAHOO.widget.Module.CSS_MODULE
 
827
    * @static
 
828
    * @final
 
829
    * @type String
 
830
    */
 
831
    Module.CSS_MODULE = "yui-module";
 
832
    
 
833
    /**
 
834
    * Constant representing the module header
 
835
    * @property YAHOO.widget.Module.CSS_HEADER
 
836
    * @static
 
837
    * @final
 
838
    * @type String
 
839
    */
 
840
    Module.CSS_HEADER = "hd";
 
841
 
 
842
    /**
 
843
    * Constant representing the module body
 
844
    * @property YAHOO.widget.Module.CSS_BODY
 
845
    * @static
 
846
    * @final
 
847
    * @type String
 
848
    */
 
849
    Module.CSS_BODY = "bd";
 
850
    
 
851
    /**
 
852
    * Constant representing the module footer
 
853
    * @property YAHOO.widget.Module.CSS_FOOTER
 
854
    * @static
 
855
    * @final
 
856
    * @type String
 
857
    */
 
858
    Module.CSS_FOOTER = "ft";
 
859
    
 
860
    /**
 
861
    * Constant representing the url for the "src" attribute of the iframe 
 
862
    * used to monitor changes to the browser's base font size
 
863
    * @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
 
864
    * @static
 
865
    * @final
 
866
    * @type String
 
867
    */
 
868
    Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
 
869
    
 
870
    /**
 
871
    * Singleton CustomEvent fired when the font size is changed in the browser.
 
872
    * Opera's "zoom" functionality currently does not support text 
 
873
    * size detection.
 
874
    * @event YAHOO.widget.Module.textResizeEvent
 
875
    */
 
876
    Module.textResizeEvent = new CustomEvent("textResize");
 
877
 
 
878
    function createModuleTemplate() {
 
879
 
 
880
        if (!m_oModuleTemplate) {
 
881
            m_oModuleTemplate = document.createElement("div");
 
882
            
 
883
            m_oModuleTemplate.innerHTML = ("<div class=\"" + 
 
884
                Module.CSS_HEADER + "\"></div>" + "<div class=\"" + 
 
885
                Module.CSS_BODY + "\"></div><div class=\"" + 
 
886
                Module.CSS_FOOTER + "\"></div>");
 
887
 
 
888
            m_oHeaderTemplate = m_oModuleTemplate.firstChild;
 
889
            m_oBodyTemplate = m_oHeaderTemplate.nextSibling;
 
890
            m_oFooterTemplate = m_oBodyTemplate.nextSibling;
 
891
        }
 
892
 
 
893
        return m_oModuleTemplate;
 
894
    }
 
895
 
 
896
    function createHeader() {
 
897
        if (!m_oHeaderTemplate) {
 
898
            createModuleTemplate();
 
899
        }
 
900
        return (m_oHeaderTemplate.cloneNode(false));
 
901
    }
 
902
 
 
903
    function createBody() {
 
904
        if (!m_oBodyTemplate) {
 
905
            createModuleTemplate();
 
906
        }
 
907
        return (m_oBodyTemplate.cloneNode(false));
 
908
    }
 
909
 
 
910
    function createFooter() {
 
911
        if (!m_oFooterTemplate) {
 
912
            createModuleTemplate();
 
913
        }
 
914
        return (m_oFooterTemplate.cloneNode(false));
 
915
    }
 
916
 
 
917
    Module.prototype = {
 
918
 
 
919
        /**
 
920
        * The class's constructor function
 
921
        * @property contructor
 
922
        * @type Function
 
923
        */
 
924
        constructor: Module,
 
925
        
 
926
        /**
 
927
        * The main module element that contains the header, body, and footer
 
928
        * @property element
 
929
        * @type HTMLElement
 
930
        */
 
931
        element: null,
 
932
 
 
933
        /**
 
934
        * The header element, denoted with CSS class "hd"
 
935
        * @property header
 
936
        * @type HTMLElement
 
937
        */
 
938
        header: null,
 
939
 
 
940
        /**
 
941
        * The body element, denoted with CSS class "bd"
 
942
        * @property body
 
943
        * @type HTMLElement
 
944
        */
 
945
        body: null,
 
946
 
 
947
        /**
 
948
        * The footer element, denoted with CSS class "ft"
 
949
        * @property footer
 
950
        * @type HTMLElement
 
951
        */
 
952
        footer: null,
 
953
 
 
954
        /**
 
955
        * The id of the element
 
956
        * @property id
 
957
        * @type String
 
958
        */
 
959
        id: null,
 
960
 
 
961
        /**
 
962
        * A string representing the root path for all images created by
 
963
        * a Module instance.
 
964
        * @deprecated It is recommend that any images for a Module be applied
 
965
        * via CSS using the "background-image" property.
 
966
        * @property imageRoot
 
967
        * @type String
 
968
        */
 
969
        imageRoot: Module.IMG_ROOT,
 
970
 
 
971
        /**
 
972
        * Initializes the custom events for Module which are fired 
 
973
        * automatically at appropriate times by the Module class.
 
974
        * @method initEvents
 
975
        */
 
976
        initEvents: function () {
 
977
 
 
978
            var SIGNATURE = CustomEvent.LIST;
 
979
 
 
980
            /**
 
981
            * CustomEvent fired prior to class initalization.
 
982
            * @event beforeInitEvent
 
983
            * @param {class} classRef class reference of the initializing 
 
984
            * class, such as this.beforeInitEvent.fire(Module)
 
985
            */
 
986
            this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT);
 
987
            this.beforeInitEvent.signature = SIGNATURE;
 
988
 
 
989
            /**
 
990
            * CustomEvent fired after class initalization.
 
991
            * @event initEvent
 
992
            * @param {class} classRef class reference of the initializing 
 
993
            * class, such as this.beforeInitEvent.fire(Module)
 
994
            */  
 
995
            this.initEvent = this.createEvent(EVENT_TYPES.INIT);
 
996
            this.initEvent.signature = SIGNATURE;
 
997
 
 
998
            /**
 
999
            * CustomEvent fired when the Module is appended to the DOM
 
1000
            * @event appendEvent
 
1001
            */
 
1002
            this.appendEvent = this.createEvent(EVENT_TYPES.APPEND);
 
1003
            this.appendEvent.signature = SIGNATURE;
 
1004
 
 
1005
            /**
 
1006
            * CustomEvent fired before the Module is rendered
 
1007
            * @event beforeRenderEvent
 
1008
            */
 
1009
            this.beforeRenderEvent = this.createEvent(EVENT_TYPES.BEFORE_RENDER);
 
1010
            this.beforeRenderEvent.signature = SIGNATURE;
 
1011
        
 
1012
            /**
 
1013
            * CustomEvent fired after the Module is rendered
 
1014
            * @event renderEvent
 
1015
            */
 
1016
            this.renderEvent = this.createEvent(EVENT_TYPES.RENDER);
 
1017
            this.renderEvent.signature = SIGNATURE;
 
1018
        
 
1019
            /**
 
1020
            * CustomEvent fired when the header content of the Module 
 
1021
            * is modified
 
1022
            * @event changeHeaderEvent
 
1023
            * @param {String/HTMLElement} content String/element representing 
 
1024
            * the new header content
 
1025
            */
 
1026
            this.changeHeaderEvent = this.createEvent(EVENT_TYPES.CHANGE_HEADER);
 
1027
            this.changeHeaderEvent.signature = SIGNATURE;
 
1028
            
 
1029
            /**
 
1030
            * CustomEvent fired when the body content of the Module is modified
 
1031
            * @event changeBodyEvent
 
1032
            * @param {String/HTMLElement} content String/element representing 
 
1033
            * the new body content
 
1034
            */  
 
1035
            this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY);
 
1036
            this.changeBodyEvent.signature = SIGNATURE;
 
1037
            
 
1038
            /**
 
1039
            * CustomEvent fired when the footer content of the Module 
 
1040
            * is modified
 
1041
            * @event changeFooterEvent
 
1042
            * @param {String/HTMLElement} content String/element representing 
 
1043
            * the new footer content
 
1044
            */
 
1045
            this.changeFooterEvent = this.createEvent(EVENT_TYPES.CHANGE_FOOTER);
 
1046
            this.changeFooterEvent.signature = SIGNATURE;
 
1047
        
 
1048
            /**
 
1049
            * CustomEvent fired when the content of the Module is modified
 
1050
            * @event changeContentEvent
 
1051
            */
 
1052
            this.changeContentEvent = this.createEvent(EVENT_TYPES.CHANGE_CONTENT);
 
1053
            this.changeContentEvent.signature = SIGNATURE;
 
1054
 
 
1055
            /**
 
1056
            * CustomEvent fired when the Module is destroyed
 
1057
            * @event destroyEvent
 
1058
            */
 
1059
            this.destroyEvent = this.createEvent(EVENT_TYPES.DESTORY);
 
1060
            this.destroyEvent.signature = SIGNATURE;
 
1061
 
 
1062
            /**
 
1063
            * CustomEvent fired before the Module is shown
 
1064
            * @event beforeShowEvent
 
1065
            */
 
1066
            this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW);
 
1067
            this.beforeShowEvent.signature = SIGNATURE;
 
1068
 
 
1069
            /**
 
1070
            * CustomEvent fired after the Module is shown
 
1071
            * @event showEvent
 
1072
            */
 
1073
            this.showEvent = this.createEvent(EVENT_TYPES.SHOW);
 
1074
            this.showEvent.signature = SIGNATURE;
 
1075
 
 
1076
            /**
 
1077
            * CustomEvent fired before the Module is hidden
 
1078
            * @event beforeHideEvent
 
1079
            */
 
1080
            this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE);
 
1081
            this.beforeHideEvent.signature = SIGNATURE;
 
1082
 
 
1083
            /**
 
1084
            * CustomEvent fired after the Module is hidden
 
1085
            * @event hideEvent
 
1086
            */
 
1087
            this.hideEvent = this.createEvent(EVENT_TYPES.HIDE);
 
1088
            this.hideEvent.signature = SIGNATURE;
 
1089
        }, 
 
1090
 
 
1091
        /**
 
1092
        * String representing the current user-agent platform
 
1093
        * @property platform
 
1094
        * @type String
 
1095
        */
 
1096
        platform: function () {
 
1097
            var ua = navigator.userAgent.toLowerCase();
 
1098
 
 
1099
            if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
 
1100
                return "windows";
 
1101
            } else if (ua.indexOf("macintosh") != -1) {
 
1102
                return "mac";
 
1103
            } else {
 
1104
                return false;
 
1105
            }
 
1106
        }(),
 
1107
        
 
1108
        /**
 
1109
        * String representing the user-agent of the browser
 
1110
        * @deprecated Use YAHOO.env.ua
 
1111
        * @property browser
 
1112
        * @type String
 
1113
        */
 
1114
        browser: function () {
 
1115
            var ua = navigator.userAgent.toLowerCase();
 
1116
            /*
 
1117
                 Check Opera first in case of spoof and check Safari before
 
1118
                 Gecko since Safari's user agent string includes "like Gecko"
 
1119
            */
 
1120
            if (ua.indexOf('opera') != -1) { 
 
1121
                return 'opera';
 
1122
            } else if (ua.indexOf('msie 7') != -1) {
 
1123
                return 'ie7';
 
1124
            } else if (ua.indexOf('msie') != -1) {
 
1125
                return 'ie';
 
1126
            } else if (ua.indexOf('safari') != -1) { 
 
1127
                return 'safari';
 
1128
            } else if (ua.indexOf('gecko') != -1) {
 
1129
                return 'gecko';
 
1130
            } else {
 
1131
                return false;
 
1132
            }
 
1133
        }(),
 
1134
        
 
1135
        /**
 
1136
        * Boolean representing whether or not the current browsing context is 
 
1137
        * secure (https)
 
1138
        * @property isSecure
 
1139
        * @type Boolean
 
1140
        */
 
1141
        isSecure: function () {
 
1142
            if (window.location.href.toLowerCase().indexOf("https") === 0) {
 
1143
                return true;
 
1144
            } else {
 
1145
                return false;
 
1146
            }
 
1147
        }(),
 
1148
        
 
1149
        /**
 
1150
        * Initializes the custom events for Module which are fired 
 
1151
        * automatically at appropriate times by the Module class.
 
1152
        */
 
1153
        initDefaultConfig: function () {
 
1154
            // Add properties //
 
1155
            /**
 
1156
            * Specifies whether the Module is visible on the page.
 
1157
            * @config visible
 
1158
            * @type Boolean
 
1159
            * @default true
 
1160
            */
 
1161
            this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, {
 
1162
                handler: this.configVisible, 
 
1163
                value: DEFAULT_CONFIG.VISIBLE.value, 
 
1164
                validator: DEFAULT_CONFIG.VISIBLE.validator
 
1165
            });
 
1166
 
 
1167
            /**
 
1168
            * <p>
 
1169
            * Object or array of objects representing the ContainerEffect 
 
1170
            * classes that are active for animating the container.
 
1171
            * </p>
 
1172
            * <p>
 
1173
            * <strong>NOTE:</strong> Although this configuration 
 
1174
            * property is introduced at the Module level, an out of the box
 
1175
            * implementation is not shipped for the Module class so setting
 
1176
            * the proroperty on the Module class has no effect. The Overlay 
 
1177
            * class is the first class to provide out of the box ContainerEffect 
 
1178
            * support.
 
1179
            * </p>
 
1180
            * @config effect
 
1181
            * @type Object
 
1182
            * @default null
 
1183
            */
 
1184
            this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, {
 
1185
                suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent, 
 
1186
                supercedes: DEFAULT_CONFIG.EFFECT.supercedes
 
1187
            });
 
1188
 
 
1189
            /**
 
1190
            * Specifies whether to create a special proxy iframe to monitor 
 
1191
            * for user font resizing in the document
 
1192
            * @config monitorresize
 
1193
            * @type Boolean
 
1194
            * @default true
 
1195
            */
 
1196
            this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, {
 
1197
                handler: this.configMonitorResize,
 
1198
                value: DEFAULT_CONFIG.MONITOR_RESIZE.value
 
1199
            });
 
1200
 
 
1201
            /**
 
1202
            * Specifies if the module should be rendered as the first child 
 
1203
            * of document.body or appended as the last child when render is called
 
1204
            * with document.body as the "appendToNode".
 
1205
            * <p>
 
1206
            * Appending to the body while the DOM is still being constructed can 
 
1207
            * lead to Operation Aborted errors in IE hence this flag is set to 
 
1208
            * false by default.
 
1209
            * </p>
 
1210
            * 
 
1211
            * @config appendtodocumentbody
 
1212
            * @type Boolean
 
1213
            * @default false
 
1214
            */
 
1215
            this.cfg.addProperty(DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.key, {
 
1216
                value: DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.value
 
1217
            });
 
1218
        },
 
1219
 
 
1220
        /**
 
1221
        * The Module class's initialization method, which is executed for
 
1222
        * Module and all of its subclasses. This method is automatically 
 
1223
        * called by the constructor, and  sets up all DOM references for 
 
1224
        * pre-existing markup, and creates required markup if it is not 
 
1225
        * already present.
 
1226
        * @method init
 
1227
        * @param {String} el The element ID representing the Module <em>OR</em>
 
1228
        * @param {HTMLElement} el The element representing the Module
 
1229
        * @param {Object} userConfig The configuration Object literal 
 
1230
        * containing the configuration that should be set for this module. 
 
1231
        * See configuration documentation for more details.
 
1232
        */
 
1233
        init: function (el, userConfig) {
 
1234
 
 
1235
            var elId, child;
 
1236
 
 
1237
            this.initEvents();
 
1238
            this.beforeInitEvent.fire(Module);
 
1239
 
 
1240
            /**
 
1241
            * The Module's Config object used for monitoring 
 
1242
            * configuration properties.
 
1243
            * @property cfg
 
1244
            * @type YAHOO.util.Config
 
1245
            */
 
1246
            this.cfg = new Config(this);
 
1247
 
 
1248
            if (this.isSecure) {
 
1249
                this.imageRoot = Module.IMG_ROOT_SSL;
 
1250
            }
 
1251
 
 
1252
            if (typeof el == "string") {
 
1253
                elId = el;
 
1254
                el = document.getElementById(el);
 
1255
                if (! el) {
 
1256
                    el = (createModuleTemplate()).cloneNode(false);
 
1257
                    el.id = elId;
 
1258
                }
 
1259
            }
 
1260
 
 
1261
            this.element = el;
 
1262
 
 
1263
            if (el.id) {
 
1264
                this.id = el.id;
 
1265
            }
 
1266
 
 
1267
            child = this.element.firstChild;
 
1268
 
 
1269
            if (child) {
 
1270
                var fndHd = false, fndBd = false, fndFt = false;
 
1271
                do {
 
1272
                    // We're looking for elements
 
1273
                    if (1 == child.nodeType) {
 
1274
                        if (!fndHd && Dom.hasClass(child, Module.CSS_HEADER)) {
 
1275
                            this.header = child;
 
1276
                            fndHd = true;
 
1277
                        } else if (!fndBd && Dom.hasClass(child, Module.CSS_BODY)) {
 
1278
                            this.body = child;
 
1279
                            fndBd = true;
 
1280
                        } else if (!fndFt && Dom.hasClass(child, Module.CSS_FOOTER)){
 
1281
                            this.footer = child;
 
1282
                            fndFt = true;
 
1283
                        }
 
1284
                    }
 
1285
                } while ((child = child.nextSibling));
 
1286
            }
 
1287
 
 
1288
            this.initDefaultConfig();
 
1289
 
 
1290
            Dom.addClass(this.element, Module.CSS_MODULE);
 
1291
 
 
1292
            if (userConfig) {
 
1293
                this.cfg.applyConfig(userConfig, true);
 
1294
            }
 
1295
 
 
1296
            /*
 
1297
                Subscribe to the fireQueue() method of Config so that any 
 
1298
                queued configuration changes are excecuted upon render of 
 
1299
                the Module
 
1300
            */ 
 
1301
 
 
1302
            if (!Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) {
 
1303
                this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
 
1304
            }
 
1305
 
 
1306
            this.initEvent.fire(Module);
 
1307
        },
 
1308
 
 
1309
        /**
 
1310
        * Initialize an empty IFRAME that is placed out of the visible area 
 
1311
        * that can be used to detect text resize.
 
1312
        * @method initResizeMonitor
 
1313
        */
 
1314
        initResizeMonitor: function () {
 
1315
 
 
1316
            var isGeckoWin = (YAHOO.env.ua.gecko && this.platform == "windows");
 
1317
            if (isGeckoWin) {
 
1318
                // Help prevent spinning loading icon which 
 
1319
                // started with FireFox 2.0.0.8/Win
 
1320
                var self = this;
 
1321
                setTimeout(function(){self._initResizeMonitor();}, 0);
 
1322
            } else {
 
1323
                this._initResizeMonitor();
 
1324
            }
 
1325
        },
 
1326
 
 
1327
        /**
 
1328
         * Create and initialize the text resize monitoring iframe.
 
1329
         * 
 
1330
         * @protected
 
1331
         * @method _initResizeMonitor
 
1332
         */
 
1333
        _initResizeMonitor : function() {
 
1334
 
 
1335
            var oDoc, 
 
1336
                oIFrame, 
 
1337
                sHTML;
 
1338
 
 
1339
            function fireTextResize() {
 
1340
                Module.textResizeEvent.fire();
 
1341
            }
 
1342
 
 
1343
            if (!YAHOO.env.ua.opera) {
 
1344
                oIFrame = Dom.get("_yuiResizeMonitor");
 
1345
 
 
1346
                var supportsCWResize = this._supportsCWResize();
 
1347
 
 
1348
                if (!oIFrame) {
 
1349
                    oIFrame = document.createElement("iframe");
 
1350
 
 
1351
                    if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && YAHOO.env.ua.ie) {
 
1352
                        oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL;
 
1353
                    }
 
1354
 
 
1355
                    if (!supportsCWResize) {
 
1356
                        // Can't monitor on contentWindow, so fire from inside iframe
 
1357
                        sHTML = ["<html><head><script ",
 
1358
                                 "type=\"text/javascript\">",
 
1359
                                 "window.onresize=function(){window.parent.",
 
1360
                                 "YAHOO.widget.Module.textResizeEvent.",
 
1361
                                 "fire();};<",
 
1362
                                 "\/script></head>",
 
1363
                                 "<body></body></html>"].join('');
 
1364
 
 
1365
                        oIFrame.src = "data:text/html;charset=utf-8," + encodeURIComponent(sHTML);
 
1366
                    }
 
1367
 
 
1368
                    oIFrame.id = "_yuiResizeMonitor";
 
1369
                    oIFrame.title = "Text Resize Monitor";
 
1370
                    /*
 
1371
                        Need to set "position" property before inserting the 
 
1372
                        iframe into the document or Safari's status bar will 
 
1373
                        forever indicate the iframe is loading 
 
1374
                        (See SourceForge bug #1723064)
 
1375
                    */
 
1376
                    oIFrame.style.position = "absolute";
 
1377
                    oIFrame.style.visibility = "hidden";
 
1378
 
 
1379
                    var db = document.body,
 
1380
                        fc = db.firstChild;
 
1381
                    if (fc) {
 
1382
                        db.insertBefore(oIFrame, fc);
 
1383
                    } else {
 
1384
                        db.appendChild(oIFrame);
 
1385
                    }
 
1386
 
 
1387
                    oIFrame.style.width = "10em";
 
1388
                    oIFrame.style.height = "10em";
 
1389
                    oIFrame.style.top = (-1 * oIFrame.offsetHeight) + "px";
 
1390
                    oIFrame.style.left = (-1 * oIFrame.offsetWidth) + "px";
 
1391
                    oIFrame.style.borderWidth = "0";
 
1392
                    oIFrame.style.visibility = "visible";
 
1393
 
 
1394
                    /*
 
1395
                       Don't open/close the document for Gecko like we used to, since it
 
1396
                       leads to duplicate cookies. (See SourceForge bug #1721755)
 
1397
                    */
 
1398
                    if (YAHOO.env.ua.webkit) {
 
1399
                        oDoc = oIFrame.contentWindow.document;
 
1400
                        oDoc.open();
 
1401
                        oDoc.close();
 
1402
                    }
 
1403
                }
 
1404
 
 
1405
                if (oIFrame && oIFrame.contentWindow) {
 
1406
                    Module.textResizeEvent.subscribe(this.onDomResize, this, true);
 
1407
 
 
1408
                    if (!Module.textResizeInitialized) {
 
1409
                        if (supportsCWResize) {
 
1410
                            if (!Event.on(oIFrame.contentWindow, "resize", fireTextResize)) {
 
1411
                                /*
 
1412
                                     This will fail in IE if document.domain has 
 
1413
                                     changed, so we must change the listener to 
 
1414
                                     use the oIFrame element instead
 
1415
                                */
 
1416
                                Event.on(oIFrame, "resize", fireTextResize);
 
1417
                            }
 
1418
                        }
 
1419
                        Module.textResizeInitialized = true;
 
1420
                    }
 
1421
                    this.resizeMonitor = oIFrame;
 
1422
                }
 
1423
            }
 
1424
        },
 
1425
 
 
1426
        /**
 
1427
         * Text resize monitor helper method.
 
1428
         * Determines if the browser supports resize events on iframe content windows.
 
1429
         * 
 
1430
         * @private
 
1431
         * @method _supportsCWResize
 
1432
         */
 
1433
        _supportsCWResize : function() {
 
1434
            /*
 
1435
                Gecko 1.8.0 (FF1.5), 1.8.1.0-5 (FF2) won't fire resize on contentWindow.
 
1436
                Gecko 1.8.1.6+ (FF2.0.0.6+) and all other browsers will fire resize on contentWindow.
 
1437
 
 
1438
                We don't want to start sniffing for patch versions, so fire textResize the same
 
1439
                way on all FF, until 1.9 (3.x) is out
 
1440
             */
 
1441
            var bSupported = true;
 
1442
            if (YAHOO.env.ua.gecko && YAHOO.env.ua.gecko <= 1.8) {
 
1443
                bSupported = false;
 
1444
                /*
 
1445
                var v = navigator.userAgent.match(/rv:([^\s\)]*)/); // From YAHOO.env.ua
 
1446
                if (v && v[0]) {
 
1447
                    var sv = v[0].match(/\d\.\d\.(\d)/);
 
1448
                    if (sv && sv[1]) {
 
1449
                        if (parseInt(sv[1], 10) > 0) {
 
1450
                            bSupported = true;
 
1451
                        }
 
1452
                    }
 
1453
                }
 
1454
                */
 
1455
            }
 
1456
            return bSupported;
 
1457
        },
 
1458
 
 
1459
        /**
 
1460
        * Event handler fired when the resize monitor element is resized.
 
1461
        * @method onDomResize
 
1462
        * @param {DOMEvent} e The DOM resize event
 
1463
        * @param {Object} obj The scope object passed to the handler
 
1464
        */
 
1465
        onDomResize: function (e, obj) {
 
1466
 
 
1467
            var nLeft = -1 * this.resizeMonitor.offsetWidth,
 
1468
                nTop = -1 * this.resizeMonitor.offsetHeight;
 
1469
        
 
1470
            this.resizeMonitor.style.top = nTop + "px";
 
1471
            this.resizeMonitor.style.left =  nLeft + "px";
 
1472
 
 
1473
        },
 
1474
 
 
1475
        /**
 
1476
        * Sets the Module's header content to the string specified, or appends 
 
1477
        * the passed element to the header. If no header is present, one will 
 
1478
        * be automatically created. An empty string can be passed to the method
 
1479
        * to clear the contents of the header.
 
1480
        * 
 
1481
        * @method setHeader
 
1482
        * @param {String} headerContent The string used to set the header.
 
1483
        * As a convenience, non HTMLElement objects can also be passed into 
 
1484
        * the method, and will be treated as strings, with the header innerHTML
 
1485
        * set to their default toString implementations.
 
1486
        * <em>OR</em>
 
1487
        * @param {HTMLElement} headerContent The HTMLElement to append to 
 
1488
        * <em>OR</em>
 
1489
        * @param {DocumentFragment} headerContent The document fragment 
 
1490
        * containing elements which are to be added to the header
 
1491
        */
 
1492
        setHeader: function (headerContent) {
 
1493
            var oHeader = this.header || (this.header = createHeader());
 
1494
 
 
1495
            if (headerContent.nodeName) {
 
1496
                oHeader.innerHTML = "";
 
1497
                oHeader.appendChild(headerContent);
 
1498
            } else {
 
1499
                oHeader.innerHTML = headerContent;
 
1500
            }
 
1501
 
 
1502
            this.changeHeaderEvent.fire(headerContent);
 
1503
            this.changeContentEvent.fire();
 
1504
 
 
1505
        },
 
1506
 
 
1507
        /**
 
1508
        * Appends the passed element to the header. If no header is present, 
 
1509
        * one will be automatically created.
 
1510
        * @method appendToHeader
 
1511
        * @param {HTMLElement | DocumentFragment} element The element to 
 
1512
        * append to the header. In the case of a document fragment, the
 
1513
        * children of the fragment will be appended to the header.
 
1514
        */
 
1515
        appendToHeader: function (element) {
 
1516
            var oHeader = this.header || (this.header = createHeader());
 
1517
 
 
1518
            oHeader.appendChild(element);
 
1519
 
 
1520
            this.changeHeaderEvent.fire(element);
 
1521
            this.changeContentEvent.fire();
 
1522
 
 
1523
        },
 
1524
 
 
1525
        /**
 
1526
        * Sets the Module's body content to the HTML specified. 
 
1527
        * 
 
1528
        * If no body is present, one will be automatically created. 
 
1529
        * 
 
1530
        * An empty string can be passed to the method to clear the contents of the body.
 
1531
        * @method setBody
 
1532
        * @param {String} bodyContent The HTML used to set the body. 
 
1533
        * As a convenience, non HTMLElement objects can also be passed into 
 
1534
        * the method, and will be treated as strings, with the body innerHTML
 
1535
        * set to their default toString implementations.
 
1536
        * <em>OR</em>
 
1537
        * @param {HTMLElement} bodyContent The HTMLElement to add as the first and only
 
1538
        * child of the body element.
 
1539
        * <em>OR</em>
 
1540
        * @param {DocumentFragment} bodyContent The document fragment 
 
1541
        * containing elements which are to be added to the body
 
1542
        */
 
1543
        setBody: function (bodyContent) {
 
1544
            var oBody = this.body || (this.body = createBody());
 
1545
 
 
1546
            if (bodyContent.nodeName) {
 
1547
                oBody.innerHTML = "";
 
1548
                oBody.appendChild(bodyContent);
 
1549
            } else {
 
1550
                oBody.innerHTML = bodyContent;
 
1551
            }
 
1552
 
 
1553
            this.changeBodyEvent.fire(bodyContent);
 
1554
            this.changeContentEvent.fire();
 
1555
        },
 
1556
 
 
1557
        /**
 
1558
        * Appends the passed element to the body. If no body is present, one 
 
1559
        * will be automatically created.
 
1560
        * @method appendToBody
 
1561
        * @param {HTMLElement | DocumentFragment} element The element to 
 
1562
        * append to the body. In the case of a document fragment, the
 
1563
        * children of the fragment will be appended to the body.
 
1564
        * 
 
1565
        */
 
1566
        appendToBody: function (element) {
 
1567
            var oBody = this.body || (this.body = createBody());
 
1568
        
 
1569
            oBody.appendChild(element);
 
1570
 
 
1571
            this.changeBodyEvent.fire(element);
 
1572
            this.changeContentEvent.fire();
 
1573
 
 
1574
        },
 
1575
        
 
1576
        /**
 
1577
        * Sets the Module's footer content to the HTML specified, or appends 
 
1578
        * the passed element to the footer. If no footer is present, one will 
 
1579
        * be automatically created. An empty string can be passed to the method
 
1580
        * to clear the contents of the footer.
 
1581
        * @method setFooter
 
1582
        * @param {String} footerContent The HTML used to set the footer 
 
1583
        * As a convenience, non HTMLElement objects can also be passed into 
 
1584
        * the method, and will be treated as strings, with the footer innerHTML
 
1585
        * set to their default toString implementations.
 
1586
        * <em>OR</em>
 
1587
        * @param {HTMLElement} footerContent The HTMLElement to append to 
 
1588
        * the footer
 
1589
        * <em>OR</em>
 
1590
        * @param {DocumentFragment} footerContent The document fragment containing 
 
1591
        * elements which are to be added to the footer
 
1592
        */
 
1593
        setFooter: function (footerContent) {
 
1594
 
 
1595
            var oFooter = this.footer || (this.footer = createFooter());
 
1596
 
 
1597
            if (footerContent.nodeName) {
 
1598
                oFooter.innerHTML = "";
 
1599
                oFooter.appendChild(footerContent);
 
1600
            } else {
 
1601
                oFooter.innerHTML = footerContent;
 
1602
            }
 
1603
 
 
1604
            this.changeFooterEvent.fire(footerContent);
 
1605
            this.changeContentEvent.fire();
 
1606
        },
 
1607
 
 
1608
        /**
 
1609
        * Appends the passed element to the footer. If no footer is present, 
 
1610
        * one will be automatically created.
 
1611
        * @method appendToFooter
 
1612
        * @param {HTMLElement | DocumentFragment} element The element to 
 
1613
        * append to the footer. In the case of a document fragment, the
 
1614
        * children of the fragment will be appended to the footer
 
1615
        */
 
1616
        appendToFooter: function (element) {
 
1617
 
 
1618
            var oFooter = this.footer || (this.footer = createFooter());
 
1619
 
 
1620
            oFooter.appendChild(element);
 
1621
 
 
1622
            this.changeFooterEvent.fire(element);
 
1623
            this.changeContentEvent.fire();
 
1624
 
 
1625
        },
 
1626
 
 
1627
        /**
 
1628
        * Renders the Module by inserting the elements that are not already 
 
1629
        * in the main Module into their correct places. Optionally appends 
 
1630
        * the Module to the specified node prior to the render's execution. 
 
1631
        * <p>
 
1632
        * For Modules without existing markup, the appendToNode argument 
 
1633
        * is REQUIRED. If this argument is ommitted and the current element is 
 
1634
        * not present in the document, the function will return false, 
 
1635
        * indicating that the render was a failure.
 
1636
        * </p>
 
1637
        * <p>
 
1638
        * NOTE: As of 2.3.1, if the appendToNode is the document's body element
 
1639
        * then the module is rendered as the first child of the body element, 
 
1640
        * and not appended to it, to avoid Operation Aborted errors in IE when 
 
1641
        * rendering the module before window's load event is fired. You can 
 
1642
        * use the appendtodocumentbody configuration property to change this 
 
1643
        * to append to document.body if required.
 
1644
        * </p>
 
1645
        * @method render
 
1646
        * @param {String} appendToNode The element id to which the Module 
 
1647
        * should be appended to prior to rendering <em>OR</em>
 
1648
        * @param {HTMLElement} appendToNode The element to which the Module 
 
1649
        * should be appended to prior to rendering
 
1650
        * @param {HTMLElement} moduleElement OPTIONAL. The element that 
 
1651
        * represents the actual Standard Module container.
 
1652
        * @return {Boolean} Success or failure of the render
 
1653
        */
 
1654
        render: function (appendToNode, moduleElement) {
 
1655
 
 
1656
            var me = this,
 
1657
                firstChild;
 
1658
 
 
1659
            function appendTo(parentNode) {
 
1660
                if (typeof parentNode == "string") {
 
1661
                    parentNode = document.getElementById(parentNode);
 
1662
                }
 
1663
 
 
1664
                if (parentNode) {
 
1665
                    me._addToParent(parentNode, me.element);
 
1666
                    me.appendEvent.fire();
 
1667
                }
 
1668
            }
 
1669
 
 
1670
            this.beforeRenderEvent.fire();
 
1671
 
 
1672
            if (! moduleElement) {
 
1673
                moduleElement = this.element;
 
1674
            }
 
1675
 
 
1676
            if (appendToNode) {
 
1677
                appendTo(appendToNode);
 
1678
            } else { 
 
1679
                // No node was passed in. If the element is not already in the Dom, this fails
 
1680
                if (! Dom.inDocument(this.element)) {
 
1681
                    YAHOO.log("Render failed. Must specify appendTo node if " + " Module isn't already in the DOM.", "error");
 
1682
                    return false;
 
1683
                }
 
1684
            }
 
1685
 
 
1686
            // Need to get everything into the DOM if it isn't already
 
1687
            if (this.header && ! Dom.inDocument(this.header)) {
 
1688
                // There is a header, but it's not in the DOM yet. Need to add it.
 
1689
                firstChild = moduleElement.firstChild;
 
1690
                if (firstChild) {
 
1691
                    moduleElement.insertBefore(this.header, firstChild);
 
1692
                } else {
 
1693
                    moduleElement.appendChild(this.header);
 
1694
                }
 
1695
            }
 
1696
 
 
1697
            if (this.body && ! Dom.inDocument(this.body)) {
 
1698
                // There is a body, but it's not in the DOM yet. Need to add it.                
 
1699
                if (this.footer && Dom.isAncestor(this.moduleElement, this.footer)) {
 
1700
                    moduleElement.insertBefore(this.body, this.footer);
 
1701
                } else {
 
1702
                    moduleElement.appendChild(this.body);
 
1703
                }
 
1704
            }
 
1705
 
 
1706
            if (this.footer && ! Dom.inDocument(this.footer)) {
 
1707
                // There is a footer, but it's not in the DOM yet. Need to add it.
 
1708
                moduleElement.appendChild(this.footer);
 
1709
            }
 
1710
 
 
1711
            this.renderEvent.fire();
 
1712
            return true;
 
1713
        },
 
1714
 
 
1715
        /**
 
1716
        * Removes the Module element from the DOM and sets all child elements 
 
1717
        * to null.
 
1718
        * @method destroy
 
1719
        */
 
1720
        destroy: function () {
 
1721
 
 
1722
            var parent,
 
1723
                e;
 
1724
 
 
1725
            if (this.element) {
 
1726
                Event.purgeElement(this.element, true);
 
1727
                parent = this.element.parentNode;
 
1728
            }
 
1729
 
 
1730
            if (parent) {
 
1731
                parent.removeChild(this.element);
 
1732
            }
 
1733
        
 
1734
            this.element = null;
 
1735
            this.header = null;
 
1736
            this.body = null;
 
1737
            this.footer = null;
 
1738
 
 
1739
            Module.textResizeEvent.unsubscribe(this.onDomResize, this);
 
1740
 
 
1741
            this.cfg.destroy();
 
1742
            this.cfg = null;
 
1743
 
 
1744
            this.destroyEvent.fire();
 
1745
        },
 
1746
 
 
1747
        /**
 
1748
        * Shows the Module element by setting the visible configuration 
 
1749
        * property to true. Also fires two events: beforeShowEvent prior to 
 
1750
        * the visibility change, and showEvent after.
 
1751
        * @method show
 
1752
        */
 
1753
        show: function () {
 
1754
            this.cfg.setProperty("visible", true);
 
1755
        },
 
1756
 
 
1757
        /**
 
1758
        * Hides the Module element by setting the visible configuration 
 
1759
        * property to false. Also fires two events: beforeHideEvent prior to 
 
1760
        * the visibility change, and hideEvent after.
 
1761
        * @method hide
 
1762
        */
 
1763
        hide: function () {
 
1764
            this.cfg.setProperty("visible", false);
 
1765
        },
 
1766
        
 
1767
        // BUILT-IN EVENT HANDLERS FOR MODULE //
 
1768
        /**
 
1769
        * Default event handler for changing the visibility property of a 
 
1770
        * Module. By default, this is achieved by switching the "display" style 
 
1771
        * between "block" and "none".
 
1772
        * This method is responsible for firing showEvent and hideEvent.
 
1773
        * @param {String} type The CustomEvent type (usually the property name)
 
1774
        * @param {Object[]} args The CustomEvent arguments. For configuration 
 
1775
        * handlers, args[0] will equal the newly applied value for the property.
 
1776
        * @param {Object} obj The scope object. For configuration handlers, 
 
1777
        * this will usually equal the owner.
 
1778
        * @method configVisible
 
1779
        */
 
1780
        configVisible: function (type, args, obj) {
 
1781
            var visible = args[0];
 
1782
            if (visible) {
 
1783
                this.beforeShowEvent.fire();
 
1784
                Dom.setStyle(this.element, "display", "block");
 
1785
                this.showEvent.fire();
 
1786
            } else {
 
1787
                this.beforeHideEvent.fire();
 
1788
                Dom.setStyle(this.element, "display", "none");
 
1789
                this.hideEvent.fire();
 
1790
            }
 
1791
        },
 
1792
        
 
1793
        /**
 
1794
        * Default event handler for the "monitorresize" configuration property
 
1795
        * @param {String} type The CustomEvent type (usually the property name)
 
1796
        * @param {Object[]} args The CustomEvent arguments. For configuration 
 
1797
        * handlers, args[0] will equal the newly applied value for the property.
 
1798
        * @param {Object} obj The scope object. For configuration handlers, 
 
1799
        * this will usually equal the owner.
 
1800
        * @method configMonitorResize
 
1801
        */
 
1802
        configMonitorResize: function (type, args, obj) {
 
1803
            var monitor = args[0];
 
1804
            if (monitor) {
 
1805
                this.initResizeMonitor();
 
1806
            } else {
 
1807
                Module.textResizeEvent.unsubscribe(this.onDomResize, this, true);
 
1808
                this.resizeMonitor = null;
 
1809
            }
 
1810
        },
 
1811
 
 
1812
        /**
 
1813
         * This method is a protected helper, used when constructing the DOM structure for the module 
 
1814
         * to account for situations which may cause Operation Aborted errors in IE. It should not 
 
1815
         * be used for general DOM construction.
 
1816
         * <p>
 
1817
         * If the parentNode is not document.body, the element is appended as the last element.
 
1818
         * </p>
 
1819
         * <p>
 
1820
         * If the parentNode is document.body the element is added as the first child to help
 
1821
         * prevent Operation Aborted errors in IE.
 
1822
         * </p>
 
1823
         *
 
1824
         * @param {parentNode} The HTML element to which the element will be added
 
1825
         * @param {element} The HTML element to be added to parentNode's children
 
1826
         * @method _addToParent
 
1827
         * @protected
 
1828
         */
 
1829
        _addToParent: function(parentNode, element) {
 
1830
            if (!this.cfg.getProperty("appendtodocumentbody") && parentNode === document.body && parentNode.firstChild) {
 
1831
                parentNode.insertBefore(element, parentNode.firstChild);
 
1832
            } else {
 
1833
                parentNode.appendChild(element);
 
1834
            }
 
1835
        },
 
1836
 
 
1837
        /**
 
1838
        * Returns a String representation of the Object.
 
1839
        * @method toString
 
1840
        * @return {String} The string representation of the Module
 
1841
        */
 
1842
        toString: function () {
 
1843
            return "Module " + this.id;
 
1844
        }
 
1845
    };
 
1846
 
 
1847
    YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
 
1848
 
 
1849
}());
 
1850
 
 
1851
(function () {
 
1852
 
 
1853
    /**
 
1854
    * Overlay is a Module that is absolutely positioned above the page flow. It 
 
1855
    * has convenience methods for positioning and sizing, as well as options for 
 
1856
    * controlling zIndex and constraining the Overlay's position to the current 
 
1857
    * visible viewport. Overlay also contains a dynamicly generated IFRAME which 
 
1858
    * is placed beneath it for Internet Explorer 6 and 5.x so that it will be 
 
1859
    * properly rendered above SELECT elements.
 
1860
    * @namespace YAHOO.widget
 
1861
    * @class Overlay
 
1862
    * @extends YAHOO.widget.Module
 
1863
    * @param {String} el The element ID representing the Overlay <em>OR</em>
 
1864
    * @param {HTMLElement} el The element representing the Overlay
 
1865
    * @param {Object} userConfig The configuration object literal containing 
 
1866
    * the configuration that should be set for this Overlay. See configuration 
 
1867
    * documentation for more details.
 
1868
    * @constructor
 
1869
    */
 
1870
    YAHOO.widget.Overlay = function (el, userConfig) {
 
1871
        YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
 
1872
    };
 
1873
 
 
1874
    var Lang = YAHOO.lang,
 
1875
        CustomEvent = YAHOO.util.CustomEvent,
 
1876
        Module = YAHOO.widget.Module,
 
1877
        Event = YAHOO.util.Event,
 
1878
        Dom = YAHOO.util.Dom,
 
1879
        Config = YAHOO.util.Config,
 
1880
        UA = YAHOO.env.ua,
 
1881
        Overlay = YAHOO.widget.Overlay,
 
1882
 
 
1883
        _SUBSCRIBE = "subscribe",
 
1884
        _UNSUBSCRIBE = "unsubscribe",
 
1885
 
 
1886
        m_oIFrameTemplate,
 
1887
 
 
1888
        /**
 
1889
        * Constant representing the name of the Overlay's events
 
1890
        * @property EVENT_TYPES
 
1891
        * @private
 
1892
        * @final
 
1893
        * @type Object
 
1894
        */
 
1895
        EVENT_TYPES = {
 
1896
            "BEFORE_MOVE": "beforeMove",
 
1897
            "MOVE": "move"
 
1898
        },
 
1899
 
 
1900
        /**
 
1901
        * Constant representing the Overlay's configuration properties
 
1902
        * @property DEFAULT_CONFIG
 
1903
        * @private
 
1904
        * @final
 
1905
        * @type Object
 
1906
        */
 
1907
        DEFAULT_CONFIG = {
 
1908
 
 
1909
            "X": { 
 
1910
                key: "x", 
 
1911
                validator: Lang.isNumber, 
 
1912
                suppressEvent: true, 
 
1913
                supercedes: ["iframe"]
 
1914
            },
 
1915
 
 
1916
            "Y": { 
 
1917
                key: "y", 
 
1918
                validator: Lang.isNumber, 
 
1919
                suppressEvent: true, 
 
1920
                supercedes: ["iframe"]
 
1921
            },
 
1922
 
 
1923
            "XY": { 
 
1924
                key: "xy", 
 
1925
                suppressEvent: true, 
 
1926
                supercedes: ["iframe"] 
 
1927
            },
 
1928
 
 
1929
            "CONTEXT": { 
 
1930
                key: "context", 
 
1931
                suppressEvent: true, 
 
1932
                supercedes: ["iframe"] 
 
1933
            },
 
1934
 
 
1935
            "FIXED_CENTER": { 
 
1936
                key: "fixedcenter", 
 
1937
                value: false, 
 
1938
                validator: Lang.isBoolean, 
 
1939
                supercedes: ["iframe", "visible"] 
 
1940
            },
 
1941
 
 
1942
            "WIDTH": { 
 
1943
                key: "width",
 
1944
                suppressEvent: true,
 
1945
                supercedes: ["context", "fixedcenter", "iframe"]
 
1946
            }, 
 
1947
 
 
1948
            "HEIGHT": { 
 
1949
                key: "height", 
 
1950
                suppressEvent: true, 
 
1951
                supercedes: ["context", "fixedcenter", "iframe"] 
 
1952
            },
 
1953
 
 
1954
            "AUTO_FILL_HEIGHT" : {
 
1955
                key: "autofillheight",
 
1956
                supressEvent: true,
 
1957
                supercedes: ["height"],
 
1958
                value:"body"
 
1959
            },
 
1960
 
 
1961
            "ZINDEX": { 
 
1962
                key: "zindex", 
 
1963
                value: null 
 
1964
            },
 
1965
 
 
1966
            "CONSTRAIN_TO_VIEWPORT": { 
 
1967
                key: "constraintoviewport", 
 
1968
                value: false, 
 
1969
                validator: Lang.isBoolean, 
 
1970
                supercedes: ["iframe", "x", "y", "xy"]
 
1971
            }, 
 
1972
 
 
1973
            "IFRAME": { 
 
1974
                key: "iframe", 
 
1975
                value: (UA.ie == 6 ? true : false), 
 
1976
                validator: Lang.isBoolean, 
 
1977
                supercedes: ["zindex"] 
 
1978
            },
 
1979
            
 
1980
            "PREVENT_CONTEXT_OVERLAP": {
 
1981
                key: "preventcontextoverlap",
 
1982
                value: false,
 
1983
                validator: Lang.isBoolean,  
 
1984
                supercedes: ["constraintoviewport"]
 
1985
            }
 
1986
            
 
1987
        };
 
1988
 
 
1989
    /**
 
1990
    * The URL that will be placed in the iframe
 
1991
    * @property YAHOO.widget.Overlay.IFRAME_SRC
 
1992
    * @static
 
1993
    * @final
 
1994
    * @type String
 
1995
    */
 
1996
    Overlay.IFRAME_SRC = "javascript:false;";
 
1997
 
 
1998
    /**
 
1999
    * Number representing how much the iframe shim should be offset from each 
 
2000
    * side of an Overlay instance, in pixels.
 
2001
    * @property YAHOO.widget.Overlay.IFRAME_SRC
 
2002
    * @default 3
 
2003
    * @static
 
2004
    * @final
 
2005
    * @type Number
 
2006
    */
 
2007
    Overlay.IFRAME_OFFSET = 3;
 
2008
 
 
2009
    /**
 
2010
    * Number representing the minimum distance an Overlay instance should be 
 
2011
    * positioned relative to the boundaries of the browser's viewport, in pixels.
 
2012
    * @property YAHOO.widget.Overlay.VIEWPORT_OFFSET
 
2013
    * @default 10
 
2014
    * @static
 
2015
    * @final
 
2016
    * @type Number
 
2017
    */
 
2018
    Overlay.VIEWPORT_OFFSET = 10;
 
2019
 
 
2020
    /**
 
2021
    * Constant representing the top left corner of an element, used for 
 
2022
    * configuring the context element alignment
 
2023
    * @property YAHOO.widget.Overlay.TOP_LEFT
 
2024
    * @static
 
2025
    * @final
 
2026
    * @type String
 
2027
    */
 
2028
    Overlay.TOP_LEFT = "tl";
 
2029
 
 
2030
    /**
 
2031
    * Constant representing the top right corner of an element, used for 
 
2032
    * configuring the context element alignment
 
2033
    * @property YAHOO.widget.Overlay.TOP_RIGHT
 
2034
    * @static
 
2035
    * @final
 
2036
    * @type String
 
2037
    */
 
2038
    Overlay.TOP_RIGHT = "tr";
 
2039
 
 
2040
    /**
 
2041
    * Constant representing the top bottom left corner of an element, used for 
 
2042
    * configuring the context element alignment
 
2043
    * @property YAHOO.widget.Overlay.BOTTOM_LEFT
 
2044
    * @static
 
2045
    * @final
 
2046
    * @type String
 
2047
    */
 
2048
    Overlay.BOTTOM_LEFT = "bl";
 
2049
 
 
2050
    /**
 
2051
    * Constant representing the bottom right corner of an element, used for 
 
2052
    * configuring the context element alignment
 
2053
    * @property YAHOO.widget.Overlay.BOTTOM_RIGHT
 
2054
    * @static
 
2055
    * @final
 
2056
    * @type String
 
2057
    */
 
2058
    Overlay.BOTTOM_RIGHT = "br";
 
2059
 
 
2060
    /**
 
2061
    * Constant representing the default CSS class used for an Overlay
 
2062
    * @property YAHOO.widget.Overlay.CSS_OVERLAY
 
2063
    * @static
 
2064
    * @final
 
2065
    * @type String
 
2066
    */
 
2067
    Overlay.CSS_OVERLAY = "yui-overlay";
 
2068
 
 
2069
    /**
 
2070
     * Constant representing the names of the standard module elements
 
2071
     * used in the overlay.
 
2072
     * @property YAHOO.widget.Overlay.STD_MOD_RE
 
2073
     * @static
 
2074
     * @final
 
2075
     * @type RegExp
 
2076
     */
 
2077
    Overlay.STD_MOD_RE = /^\s*?(body|footer|header)\s*?$/i;
 
2078
 
 
2079
    /**
 
2080
    * A singleton CustomEvent used for reacting to the DOM event for 
 
2081
    * window scroll
 
2082
    * @event YAHOO.widget.Overlay.windowScrollEvent
 
2083
    */
 
2084
    Overlay.windowScrollEvent = new CustomEvent("windowScroll");
 
2085
 
 
2086
    /**
 
2087
    * A singleton CustomEvent used for reacting to the DOM event for
 
2088
    * window resize
 
2089
    * @event YAHOO.widget.Overlay.windowResizeEvent
 
2090
    */
 
2091
    Overlay.windowResizeEvent = new CustomEvent("windowResize");
 
2092
 
 
2093
    /**
 
2094
    * The DOM event handler used to fire the CustomEvent for window scroll
 
2095
    * @method YAHOO.widget.Overlay.windowScrollHandler
 
2096
    * @static
 
2097
    * @param {DOMEvent} e The DOM scroll event
 
2098
    */
 
2099
    Overlay.windowScrollHandler = function (e) {
 
2100
        var t = Event.getTarget(e);
 
2101
 
 
2102
        // - Webkit (Safari 2/3) and Opera 9.2x bubble scroll events from elements to window
 
2103
        // - FF2/3 and IE6/7, Opera 9.5x don't bubble scroll events from elements to window
 
2104
        // - IE doesn't recognize scroll registered on the document.
 
2105
        //
 
2106
        // Also, when document view is scrolled, IE doesn't provide a target, 
 
2107
        // rest of the browsers set target to window.document, apart from opera 
 
2108
        // which sets target to window.
 
2109
        if (!t || t === window || t === window.document) {
 
2110
            if (UA.ie) {
 
2111
 
 
2112
                if (! window.scrollEnd) {
 
2113
                    window.scrollEnd = -1;
 
2114
                }
 
2115
 
 
2116
                clearTimeout(window.scrollEnd);
 
2117
        
 
2118
                window.scrollEnd = setTimeout(function () { 
 
2119
                    Overlay.windowScrollEvent.fire(); 
 
2120
                }, 1);
 
2121
        
 
2122
            } else {
 
2123
                Overlay.windowScrollEvent.fire();
 
2124
            }
 
2125
        }
 
2126
    };
 
2127
 
 
2128
    /**
 
2129
    * The DOM event handler used to fire the CustomEvent for window resize
 
2130
    * @method YAHOO.widget.Overlay.windowResizeHandler
 
2131
    * @static
 
2132
    * @param {DOMEvent} e The DOM resize event
 
2133
    */
 
2134
    Overlay.windowResizeHandler = function (e) {
 
2135
 
 
2136
        if (UA.ie) {
 
2137
            if (! window.resizeEnd) {
 
2138
                window.resizeEnd = -1;
 
2139
            }
 
2140
 
 
2141
            clearTimeout(window.resizeEnd);
 
2142
 
 
2143
            window.resizeEnd = setTimeout(function () {
 
2144
                Overlay.windowResizeEvent.fire(); 
 
2145
            }, 100);
 
2146
        } else {
 
2147
            Overlay.windowResizeEvent.fire();
 
2148
        }
 
2149
    };
 
2150
 
 
2151
    /**
 
2152
    * A boolean that indicated whether the window resize and scroll events have 
 
2153
    * already been subscribed to.
 
2154
    * @property YAHOO.widget.Overlay._initialized
 
2155
    * @private
 
2156
    * @type Boolean
 
2157
    */
 
2158
    Overlay._initialized = null;
 
2159
 
 
2160
    if (Overlay._initialized === null) {
 
2161
        Event.on(window, "scroll", Overlay.windowScrollHandler);
 
2162
        Event.on(window, "resize", Overlay.windowResizeHandler);
 
2163
        Overlay._initialized = true;
 
2164
    }
 
2165
 
 
2166
    /**
 
2167
     * Internal map of special event types, which are provided
 
2168
     * by the instance. It maps the event type to the custom event 
 
2169
     * instance. Contains entries for the "windowScroll", "windowResize" and
 
2170
     * "textResize" static container events.
 
2171
     *
 
2172
     * @property YAHOO.widget.Overlay._TRIGGER_MAP
 
2173
     * @type Object
 
2174
     * @static
 
2175
     * @private
 
2176
     */
 
2177
    Overlay._TRIGGER_MAP = {
 
2178
        "windowScroll" : Overlay.windowScrollEvent,
 
2179
        "windowResize" : Overlay.windowResizeEvent,
 
2180
        "textResize"   : Module.textResizeEvent
 
2181
    };
 
2182
 
 
2183
    YAHOO.extend(Overlay, Module, {
 
2184
 
 
2185
        /**
 
2186
         * <p>
 
2187
         * Array of default event types which will trigger
 
2188
         * context alignment for the Overlay class.
 
2189
         * </p>
 
2190
         * <p>The array is empty by default for Overlay,
 
2191
         * but maybe populated in future releases, so classes extending
 
2192
         * Overlay which need to define their own set of CONTEXT_TRIGGERS
 
2193
         * should concatenate their super class's prototype.CONTEXT_TRIGGERS 
 
2194
         * value with their own array of values.
 
2195
         * </p>
 
2196
         * <p>
 
2197
         * E.g.:
 
2198
         * <code>CustomOverlay.prototype.CONTEXT_TRIGGERS = YAHOO.widget.Overlay.prototype.CONTEXT_TRIGGERS.concat(["windowScroll"]);</code>
 
2199
         * </p>
 
2200
         * 
 
2201
         * @property CONTEXT_TRIGGERS
 
2202
         * @type Array
 
2203
         * @final
 
2204
         */
 
2205
        CONTEXT_TRIGGERS : [],
 
2206
 
 
2207
        /**
 
2208
        * The Overlay initialization method, which is executed for Overlay and  
 
2209
        * all of its subclasses. This method is automatically called by the 
 
2210
        * constructor, and  sets up all DOM references for pre-existing markup, 
 
2211
        * and creates required markup if it is not already present.
 
2212
        * @method init
 
2213
        * @param {String} el The element ID representing the Overlay <em>OR</em>
 
2214
        * @param {HTMLElement} el The element representing the Overlay
 
2215
        * @param {Object} userConfig The configuration object literal 
 
2216
        * containing the configuration that should be set for this Overlay. 
 
2217
        * See configuration documentation for more details.
 
2218
        */
 
2219
        init: function (el, userConfig) {
 
2220
 
 
2221
            /*
 
2222
                 Note that we don't pass the user config in here yet because we
 
2223
                 only want it executed once, at the lowest subclass level
 
2224
            */
 
2225
 
 
2226
            Overlay.superclass.init.call(this, el/*, userConfig*/);
 
2227
 
 
2228
            this.beforeInitEvent.fire(Overlay);
 
2229
 
 
2230
            Dom.addClass(this.element, Overlay.CSS_OVERLAY);
 
2231
 
 
2232
            if (userConfig) {
 
2233
                this.cfg.applyConfig(userConfig, true);
 
2234
            }
 
2235
 
 
2236
            if (this.platform == "mac" && UA.gecko) {
 
2237
 
 
2238
                if (! Config.alreadySubscribed(this.showEvent,
 
2239
                    this.showMacGeckoScrollbars, this)) {
 
2240
 
 
2241
                    this.showEvent.subscribe(this.showMacGeckoScrollbars, 
 
2242
                        this, true);
 
2243
 
 
2244
                }
 
2245
 
 
2246
                if (! Config.alreadySubscribed(this.hideEvent, 
 
2247
                    this.hideMacGeckoScrollbars, this)) {
 
2248
 
 
2249
                    this.hideEvent.subscribe(this.hideMacGeckoScrollbars, 
 
2250
                        this, true);
 
2251
 
 
2252
                }
 
2253
            }
 
2254
 
 
2255
            this.initEvent.fire(Overlay);
 
2256
        },
 
2257
        
 
2258
        /**
 
2259
        * Initializes the custom events for Overlay which are fired  
 
2260
        * automatically at appropriate times by the Overlay class.
 
2261
        * @method initEvents
 
2262
        */
 
2263
        initEvents: function () {
 
2264
 
 
2265
            Overlay.superclass.initEvents.call(this);
 
2266
 
 
2267
            var SIGNATURE = CustomEvent.LIST;
 
2268
 
 
2269
            /**
 
2270
            * CustomEvent fired before the Overlay is moved.
 
2271
            * @event beforeMoveEvent
 
2272
            * @param {Number} x x coordinate
 
2273
            * @param {Number} y y coordinate
 
2274
            */
 
2275
            this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
 
2276
            this.beforeMoveEvent.signature = SIGNATURE;
 
2277
 
 
2278
            /**
 
2279
            * CustomEvent fired after the Overlay is moved.
 
2280
            * @event moveEvent
 
2281
            * @param {Number} x x coordinate
 
2282
            * @param {Number} y y coordinate
 
2283
            */
 
2284
            this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
 
2285
            this.moveEvent.signature = SIGNATURE;
 
2286
 
 
2287
        },
 
2288
        
 
2289
        /**
 
2290
        * Initializes the class's configurable properties which can be changed 
 
2291
        * using the Overlay's Config object (cfg).
 
2292
        * @method initDefaultConfig
 
2293
        */
 
2294
        initDefaultConfig: function () {
 
2295
    
 
2296
            Overlay.superclass.initDefaultConfig.call(this);
 
2297
 
 
2298
            var cfg = this.cfg;
 
2299
 
 
2300
            // Add overlay config properties //
 
2301
            
 
2302
            /**
 
2303
            * The absolute x-coordinate position of the Overlay
 
2304
            * @config x
 
2305
            * @type Number
 
2306
            * @default null
 
2307
            */
 
2308
            cfg.addProperty(DEFAULT_CONFIG.X.key, { 
 
2309
    
 
2310
                handler: this.configX, 
 
2311
                validator: DEFAULT_CONFIG.X.validator, 
 
2312
                suppressEvent: DEFAULT_CONFIG.X.suppressEvent, 
 
2313
                supercedes: DEFAULT_CONFIG.X.supercedes
 
2314
    
 
2315
            });
 
2316
 
 
2317
            /**
 
2318
            * The absolute y-coordinate position of the Overlay
 
2319
            * @config y
 
2320
            * @type Number
 
2321
            * @default null
 
2322
            */
 
2323
            cfg.addProperty(DEFAULT_CONFIG.Y.key, {
 
2324
 
 
2325
                handler: this.configY, 
 
2326
                validator: DEFAULT_CONFIG.Y.validator, 
 
2327
                suppressEvent: DEFAULT_CONFIG.Y.suppressEvent, 
 
2328
                supercedes: DEFAULT_CONFIG.Y.supercedes
 
2329
 
 
2330
            });
 
2331
 
 
2332
            /**
 
2333
            * An array with the absolute x and y positions of the Overlay
 
2334
            * @config xy
 
2335
            * @type Number[]
 
2336
            * @default null
 
2337
            */
 
2338
            cfg.addProperty(DEFAULT_CONFIG.XY.key, {
 
2339
                handler: this.configXY, 
 
2340
                suppressEvent: DEFAULT_CONFIG.XY.suppressEvent, 
 
2341
                supercedes: DEFAULT_CONFIG.XY.supercedes
 
2342
            });
 
2343
 
 
2344
            /**
 
2345
            * <p>
 
2346
            * The array of context arguments for context-sensitive positioning. 
 
2347
            * </p>
 
2348
            *
 
2349
            * <p>
 
2350
            * The format of the array is: <code>[contextElementOrId, overlayCorner, contextCorner, arrayOfTriggerEvents (optional)]</code>, the
 
2351
            * the 4 array elements described in detail below:
 
2352
            * </p>
 
2353
            *
 
2354
            * <dl>
 
2355
            * <dt>contextElementOrId &#60;String|HTMLElement&#62;</dt>
 
2356
            * <dd>A reference to the context element to which the overlay should be aligned (or it's id).</dd>
 
2357
            * <dt>overlayCorner &#60;String&#62;</dt>
 
2358
            * <dd>The corner of the overlay which is to be used for alignment. This corner will be aligned to the 
 
2359
            * corner of the context element defined by the "contextCorner" entry which follows. Supported string values are: 
 
2360
            * "tr" (top right), "tl" (top left), "br" (bottom right), or "bl" (bottom left).</dd>
 
2361
            * <dt>contextCorner &#60;String&#62;</dt>
 
2362
            * <dd>The corner of the context element which is to be used for alignment. Supported string values are the same ones listed for the "overlayCorner" entry above.</dd>
 
2363
            * <dt>arrayOfTriggerEvents (optional) &#60;Array[String|CustomEvent]&#62;</dt>
 
2364
            * <dd>
 
2365
            * <p>
 
2366
            * By default, context alignment is a one time operation, aligning the Overlay to the context element when context configuration property is set, or when the <a href="#method_align">align</a> 
 
2367
            * method is invoked. However, you can use the optional "arrayOfTriggerEvents" entry to define the list of events which should force the overlay to re-align itself with the context element. 
 
2368
            * This is useful in situations where the layout of the document may change, resulting in the context element's position being modified.
 
2369
            * </p>
 
2370
            * <p>
 
2371
            * The array can contain either event type strings for events the instance publishes (e.g. "beforeShow") or CustomEvent instances. Additionally the following
 
2372
            * 3 static container event types are also currently supported : <code>"windowResize", "windowScroll", "textResize"</code> (defined in <a href="#property__TRIGGER_MAP">_TRIGGER_MAP</a> private property).
 
2373
            * </p>
 
2374
            * </dd>
 
2375
            * </dl>
 
2376
            *
 
2377
            * <p>
 
2378
            * For example, setting this property to <code>["img1", "tl", "bl"]</code> will 
 
2379
            * align the Overlay's top left corner to the bottom left corner of the
 
2380
            * context element with id "img1".
 
2381
            * </p>
 
2382
            * <p>
 
2383
            * Adding the optional trigger values: <code>["img1", "tl", "bl", ["beforeShow", "windowResize"]]</code>,
 
2384
            * will re-align the overlay position, whenever the "beforeShow" or "windowResize" events are fired.
 
2385
            * </p>
 
2386
            *
 
2387
            * @config context
 
2388
            * @type Array
 
2389
            * @default null
 
2390
            */
 
2391
            cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
 
2392
                handler: this.configContext, 
 
2393
                suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent, 
 
2394
                supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
 
2395
            });
 
2396
 
 
2397
            /**
 
2398
            * True if the Overlay should be anchored to the center of 
 
2399
            * the viewport.
 
2400
            * @config fixedcenter
 
2401
            * @type Boolean
 
2402
            * @default false
 
2403
            */
 
2404
            cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
 
2405
                handler: this.configFixedCenter,
 
2406
                value: DEFAULT_CONFIG.FIXED_CENTER.value, 
 
2407
                validator: DEFAULT_CONFIG.FIXED_CENTER.validator, 
 
2408
                supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
 
2409
            });
 
2410
    
 
2411
            /**
 
2412
            * CSS width of the Overlay.
 
2413
            * @config width
 
2414
            * @type String
 
2415
            * @default null
 
2416
            */
 
2417
            cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
 
2418
                handler: this.configWidth, 
 
2419
                suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent, 
 
2420
                supercedes: DEFAULT_CONFIG.WIDTH.supercedes
 
2421
            });
 
2422
 
 
2423
            /**
 
2424
            * CSS height of the Overlay.
 
2425
            * @config height
 
2426
            * @type String
 
2427
            * @default null
 
2428
            */
 
2429
            cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
 
2430
                handler: this.configHeight, 
 
2431
                suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent, 
 
2432
                supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
 
2433
            });
 
2434
 
 
2435
            /**
 
2436
            * Standard module element which should auto fill out the height of the Overlay if the height config property is set.
 
2437
            * Supported values are "header", "body", "footer".
 
2438
            *
 
2439
            * @config autofillheight
 
2440
            * @type String
 
2441
            * @default null
 
2442
            */
 
2443
            cfg.addProperty(DEFAULT_CONFIG.AUTO_FILL_HEIGHT.key, {
 
2444
                handler: this.configAutoFillHeight, 
 
2445
                value : DEFAULT_CONFIG.AUTO_FILL_HEIGHT.value,
 
2446
                validator : this._validateAutoFill,
 
2447
                suppressEvent: DEFAULT_CONFIG.AUTO_FILL_HEIGHT.suppressEvent, 
 
2448
                supercedes: DEFAULT_CONFIG.AUTO_FILL_HEIGHT.supercedes
 
2449
            });
 
2450
 
 
2451
            /**
 
2452
            * CSS z-index of the Overlay.
 
2453
            * @config zIndex
 
2454
            * @type Number
 
2455
            * @default null
 
2456
            */
 
2457
            cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
 
2458
                handler: this.configzIndex,
 
2459
                value: DEFAULT_CONFIG.ZINDEX.value
 
2460
            });
 
2461
 
 
2462
            /**
 
2463
            * True if the Overlay should be prevented from being positioned 
 
2464
            * out of the viewport.
 
2465
            * @config constraintoviewport
 
2466
            * @type Boolean
 
2467
            * @default false
 
2468
            */
 
2469
            cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
 
2470
 
 
2471
                handler: this.configConstrainToViewport, 
 
2472
                value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value, 
 
2473
                validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator, 
 
2474
                supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
 
2475
 
 
2476
            });
 
2477
 
 
2478
            /**
 
2479
            * @config iframe
 
2480
            * @description Boolean indicating whether or not the Overlay should 
 
2481
            * have an IFRAME shim; used to prevent SELECT elements from 
 
2482
            * poking through an Overlay instance in IE6.  When set to "true", 
 
2483
            * the iframe shim is created when the Overlay instance is intially
 
2484
            * made visible.
 
2485
            * @type Boolean
 
2486
            * @default true for IE6 and below, false for all other browsers.
 
2487
            */
 
2488
            cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
 
2489
 
 
2490
                handler: this.configIframe, 
 
2491
                value: DEFAULT_CONFIG.IFRAME.value, 
 
2492
                validator: DEFAULT_CONFIG.IFRAME.validator, 
 
2493
                supercedes: DEFAULT_CONFIG.IFRAME.supercedes
 
2494
 
 
2495
            });
 
2496
 
 
2497
            /**
 
2498
            * @config preventcontextoverlap
 
2499
            * @description Boolean indicating whether or not the Overlay should overlap its 
 
2500
            * context element (defined using the "context" configuration property) when the 
 
2501
            * "constraintoviewport" configuration property is set to "true".
 
2502
            * @type Boolean
 
2503
            * @default false
 
2504
            */
 
2505
            cfg.addProperty(DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.key, {
 
2506
 
 
2507
                value: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.value, 
 
2508
                validator: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.validator, 
 
2509
                supercedes: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.supercedes
 
2510
 
 
2511
            });
 
2512
 
 
2513
        },
 
2514
 
 
2515
        /**
 
2516
        * Moves the Overlay to the specified position. This function is  
 
2517
        * identical to calling this.cfg.setProperty("xy", [x,y]);
 
2518
        * @method moveTo
 
2519
        * @param {Number} x The Overlay's new x position
 
2520
        * @param {Number} y The Overlay's new y position
 
2521
        */
 
2522
        moveTo: function (x, y) {
 
2523
            this.cfg.setProperty("xy", [x, y]);
 
2524
        },
 
2525
 
 
2526
        /**
 
2527
        * Adds a CSS class ("hide-scrollbars") and removes a CSS class 
 
2528
        * ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
 
2529
        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
 
2530
        * @method hideMacGeckoScrollbars
 
2531
        */
 
2532
        hideMacGeckoScrollbars: function () {
 
2533
            Dom.replaceClass(this.element, "show-scrollbars", "hide-scrollbars");
 
2534
        },
 
2535
 
 
2536
        /**
 
2537
        * Adds a CSS class ("show-scrollbars") and removes a CSS class 
 
2538
        * ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
 
2539
        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
 
2540
        * @method showMacGeckoScrollbars
 
2541
        */
 
2542
        showMacGeckoScrollbars: function () {
 
2543
            Dom.replaceClass(this.element, "hide-scrollbars", "show-scrollbars");
 
2544
        },
 
2545
 
 
2546
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
 
2547
        /**
 
2548
        * The default event handler fired when the "visible" property is 
 
2549
        * changed.  This method is responsible for firing showEvent
 
2550
        * and hideEvent.
 
2551
        * @method configVisible
 
2552
        * @param {String} type The CustomEvent type (usually the property name)
 
2553
        * @param {Object[]} args The CustomEvent arguments. For configuration
 
2554
        * handlers, args[0] will equal the newly applied value for the property.
 
2555
        * @param {Object} obj The scope object. For configuration handlers, 
 
2556
        * this will usually equal the owner.
 
2557
        */
 
2558
        configVisible: function (type, args, obj) {
 
2559
 
 
2560
            var visible = args[0],
 
2561
                currentVis = Dom.getStyle(this.element, "visibility"),
 
2562
                effect = this.cfg.getProperty("effect"),
 
2563
                effectInstances = [],
 
2564
                isMacGecko = (this.platform == "mac" && UA.gecko),
 
2565
                alreadySubscribed = Config.alreadySubscribed,
 
2566
                eff, ei, e, i, j, k, h,
 
2567
                nEffects,
 
2568
                nEffectInstances;
 
2569
 
 
2570
            if (currentVis == "inherit") {
 
2571
                e = this.element.parentNode;
 
2572
 
 
2573
                while (e.nodeType != 9 && e.nodeType != 11) {
 
2574
                    currentVis = Dom.getStyle(e, "visibility");
 
2575
 
 
2576
                    if (currentVis != "inherit") { 
 
2577
                        break; 
 
2578
                    }
 
2579
 
 
2580
                    e = e.parentNode;
 
2581
                }
 
2582
 
 
2583
                if (currentVis == "inherit") {
 
2584
                    currentVis = "visible";
 
2585
                }
 
2586
            }
 
2587
 
 
2588
            if (effect) {
 
2589
                if (effect instanceof Array) {
 
2590
                    nEffects = effect.length;
 
2591
 
 
2592
                    for (i = 0; i < nEffects; i++) {
 
2593
                        eff = effect[i];
 
2594
                        effectInstances[effectInstances.length] = 
 
2595
                            eff.effect(this, eff.duration);
 
2596
 
 
2597
                    }
 
2598
                } else {
 
2599
                    effectInstances[effectInstances.length] = 
 
2600
                        effect.effect(this, effect.duration);
 
2601
                }
 
2602
            }
 
2603
 
 
2604
 
 
2605
            if (visible) { // Show
 
2606
                if (isMacGecko) {
 
2607
                    this.showMacGeckoScrollbars();
 
2608
                }
 
2609
 
 
2610
                if (effect) { // Animate in
 
2611
                    if (visible) { // Animate in if not showing
 
2612
                        if (currentVis != "visible" || currentVis === "") {
 
2613
                            this.beforeShowEvent.fire();
 
2614
                            nEffectInstances = effectInstances.length;
 
2615
 
 
2616
                            for (j = 0; j < nEffectInstances; j++) {
 
2617
                                ei = effectInstances[j];
 
2618
                                if (j === 0 && !alreadySubscribed(
 
2619
                                        ei.animateInCompleteEvent, 
 
2620
                                        this.showEvent.fire, this.showEvent)) {
 
2621
 
 
2622
                                    /*
 
2623
                                         Delegate showEvent until end 
 
2624
                                         of animateInComplete
 
2625
                                    */
 
2626
 
 
2627
                                    ei.animateInCompleteEvent.subscribe(
 
2628
                                     this.showEvent.fire, this.showEvent, true);
 
2629
                                }
 
2630
                                ei.animateIn();
 
2631
                            }
 
2632
                        }
 
2633
                    }
 
2634
                } else { // Show
 
2635
                    if (currentVis != "visible" || currentVis === "") {
 
2636
                        this.beforeShowEvent.fire();
 
2637
 
 
2638
                        Dom.setStyle(this.element, "visibility", "visible");
 
2639
 
 
2640
                        this.cfg.refireEvent("iframe");
 
2641
                        this.showEvent.fire();
 
2642
                    }
 
2643
                }
 
2644
            } else { // Hide
 
2645
 
 
2646
                if (isMacGecko) {
 
2647
                    this.hideMacGeckoScrollbars();
 
2648
                }
 
2649
                    
 
2650
                if (effect) { // Animate out if showing
 
2651
                    if (currentVis == "visible") {
 
2652
                        this.beforeHideEvent.fire();
 
2653
 
 
2654
                        nEffectInstances = effectInstances.length;
 
2655
                        for (k = 0; k < nEffectInstances; k++) {
 
2656
                            h = effectInstances[k];
 
2657
    
 
2658
                            if (k === 0 && !alreadySubscribed(
 
2659
                                h.animateOutCompleteEvent, this.hideEvent.fire, 
 
2660
                                this.hideEvent)) {
 
2661
    
 
2662
                                /*
 
2663
                                     Delegate hideEvent until end 
 
2664
                                     of animateOutComplete
 
2665
                                */
 
2666
    
 
2667
                                h.animateOutCompleteEvent.subscribe(
 
2668
                                    this.hideEvent.fire, this.hideEvent, true);
 
2669
    
 
2670
                            }
 
2671
                            h.animateOut();
 
2672
                        }
 
2673
 
 
2674
                    } else if (currentVis === "") {
 
2675
                        Dom.setStyle(this.element, "visibility", "hidden");
 
2676
                    }
 
2677
 
 
2678
                } else { // Simple hide
 
2679
 
 
2680
                    if (currentVis == "visible" || currentVis === "") {
 
2681
                        this.beforeHideEvent.fire();
 
2682
                        Dom.setStyle(this.element, "visibility", "hidden");
 
2683
                        this.hideEvent.fire();
 
2684
                    }
 
2685
                }
 
2686
            }
 
2687
        },
 
2688
 
 
2689
        /**
 
2690
        * Center event handler used for centering on scroll/resize, but only if 
 
2691
        * the Overlay is visible
 
2692
        * @method doCenterOnDOMEvent
 
2693
        */
 
2694
        doCenterOnDOMEvent: function () {
 
2695
            if (this.cfg.getProperty("visible")) {
 
2696
                this.center();
 
2697
            }
 
2698
        },
 
2699
 
 
2700
        /**
 
2701
        * The default event handler fired when the "fixedcenter" property 
 
2702
        * is changed.
 
2703
        * @method configFixedCenter
 
2704
        * @param {String} type The CustomEvent type (usually the property name)
 
2705
        * @param {Object[]} args The CustomEvent arguments. For configuration 
 
2706
        * handlers, args[0] will equal the newly applied value for the property.
 
2707
        * @param {Object} obj The scope object. For configuration handlers, 
 
2708
        * this will usually equal the owner.
 
2709
        */
 
2710
        configFixedCenter: function (type, args, obj) {
 
2711
 
 
2712
            var val = args[0],
 
2713
                alreadySubscribed = Config.alreadySubscribed,
 
2714
                windowResizeEvent = Overlay.windowResizeEvent,
 
2715
                windowScrollEvent = Overlay.windowScrollEvent;
 
2716
 
 
2717
            if (val) {
 
2718
                this.center();
 
2719
 
 
2720
                if (!alreadySubscribed(this.beforeShowEvent, this.center, this)) {
 
2721
                    this.beforeShowEvent.subscribe(this.center);
 
2722
                }
 
2723
 
 
2724
                if (!alreadySubscribed(windowResizeEvent, this.doCenterOnDOMEvent, this)) {
 
2725
                    windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
 
2726
                }
 
2727
 
 
2728
                if (!alreadySubscribed(windowScrollEvent, this.doCenterOnDOMEvent, this)) {
 
2729
                    windowScrollEvent.subscribe(this.doCenterOnDOMEvent, this, true);
 
2730
                }
 
2731
 
 
2732
            } else {
 
2733
                this.beforeShowEvent.unsubscribe(this.center);
 
2734
 
 
2735
                windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
 
2736
                windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
 
2737
            }
 
2738
        },
 
2739
        
 
2740
        /**
 
2741
        * The default event handler fired when the "height" property is changed.
 
2742
        * @method configHeight
 
2743
        * @param {String} type The CustomEvent type (usually the property name)
 
2744
        * @param {Object[]} args The CustomEvent arguments. For configuration 
 
2745
        * handlers, args[0] will equal the newly applied value for the property.
 
2746
        * @param {Object} obj The scope object. For configuration handlers, 
 
2747
        * this will usually equal the owner.
 
2748
        */
 
2749
        configHeight: function (type, args, obj) {
 
2750
 
 
2751
            var height = args[0],
 
2752
                el = this.element;
 
2753
 
 
2754
            Dom.setStyle(el, "height", height);
 
2755
            this.cfg.refireEvent("iframe");
 
2756
        },
 
2757
 
 
2758
        /**
 
2759
         * The default event handler fired when the "autofillheight" property is changed.
 
2760
         * @method configAutoFillHeight
 
2761
         *
 
2762
         * @param {String} type The CustomEvent type (usually the property name)
 
2763
         * @param {Object[]} args The CustomEvent arguments. For configuration 
 
2764
         * handlers, args[0] will equal the newly applied value for the property.
 
2765
         * @param {Object} obj The scope object. For configuration handlers, 
 
2766
         * this will usually equal the owner.
 
2767
         */
 
2768
        configAutoFillHeight: function (type, args, obj) {
 
2769
            var fillEl = args[0],
 
2770
                currEl = this.cfg.getProperty("autofillheight");
 
2771
 
 
2772
            this.cfg.unsubscribeFromConfigEvent("height", this._autoFillOnHeightChange);
 
2773
            Module.textResizeEvent.unsubscribe("height", this._autoFillOnHeightChange);
 
2774
 
 
2775
            if (currEl && fillEl !== currEl && this[currEl]) {
 
2776
                Dom.setStyle(this[currEl], "height", "");
 
2777
            }
 
2778
 
 
2779
            if (fillEl) {
 
2780
                fillEl = Lang.trim(fillEl.toLowerCase());
 
2781
 
 
2782
                this.cfg.subscribeToConfigEvent("height", this._autoFillOnHeightChange, this[fillEl], this);
 
2783
                Module.textResizeEvent.subscribe(this._autoFillOnHeightChange, this[fillEl], this);
 
2784
 
 
2785
                this.cfg.setProperty("autofillheight", fillEl, true);
 
2786
            }
 
2787
        },
 
2788
 
 
2789
        /**
 
2790
        * The default event handler fired when the "width" property is changed.
 
2791
        * @method configWidth
 
2792
        * @param {String} type The CustomEvent type (usually the property name)
 
2793
        * @param {Object[]} args The CustomEvent arguments. For configuration 
 
2794
        * handlers, args[0] will equal the newly applied value for the property.
 
2795
        * @param {Object} obj The scope object. For configuration handlers, 
 
2796
        * this will usually equal the owner.
 
2797
        */
 
2798
        configWidth: function (type, args, obj) {
 
2799
 
 
2800
            var width = args[0],
 
2801
                el = this.element;
 
2802
 
 
2803
            Dom.setStyle(el, "width", width);
 
2804
            this.cfg.refireEvent("iframe");
 
2805
        },
 
2806
 
 
2807
        /**
 
2808
        * The default event handler fired when the "zIndex" property is changed.
 
2809
        * @method configzIndex
 
2810
        * @param {String} type The CustomEvent type (usually the property name)
 
2811
        * @param {Object[]} args The CustomEvent arguments. For configuration 
 
2812
        * handlers, args[0] will equal the newly applied value for the property.
 
2813
        * @param {Object} obj The scope object. For configuration handlers, 
 
2814
        * this will usually equal the owner.
 
2815
        */
 
2816
        configzIndex: function (type, args, obj) {
 
2817
 
 
2818
            var zIndex = args[0],
 
2819
                el = this.element;
 
2820
 
 
2821
            if (! zIndex) {
 
2822
                zIndex = Dom.getStyle(el, "zIndex");
 
2823
                if (! zIndex || isNaN(zIndex)) {
 
2824
                    zIndex = 0;
 
2825
                }
 
2826
            }
 
2827
 
 
2828
            if (this.iframe || this.cfg.getProperty("iframe") === true) {
 
2829
                if (zIndex <= 0) {
 
2830
                    zIndex = 1;
 
2831
                }
 
2832
            }
 
2833
 
 
2834
            Dom.setStyle(el, "zIndex", zIndex);
 
2835
            this.cfg.setProperty("zIndex", zIndex, true);
 
2836
 
 
2837
            if (this.iframe) {
 
2838
                this.stackIframe();
 
2839
            }
 
2840
        },
 
2841
 
 
2842
        /**
 
2843
        * The default event handler fired when the "xy" property is changed.
 
2844
        * @method configXY
 
2845
        * @param {String} type The CustomEvent type (usually the property name)
 
2846
        * @param {Object[]} args The CustomEvent arguments. For configuration 
 
2847
        * handlers, args[0] will equal the newly applied value for the property.
 
2848
        * @param {Object} obj The scope object. For configuration handlers, 
 
2849
        * this will usually equal the owner.
 
2850
        */
 
2851
        configXY: function (type, args, obj) {
 
2852
 
 
2853
            var pos = args[0],
 
2854
                x = pos[0],
 
2855
                y = pos[1];
 
2856
 
 
2857
            this.cfg.setProperty("x", x);
 
2858
            this.cfg.setProperty("y", y);
 
2859
 
 
2860
            this.beforeMoveEvent.fire([x, y]);
 
2861
 
 
2862
            x = this.cfg.getProperty("x");
 
2863
            y = this.cfg.getProperty("y");
 
2864
 
 
2865
            YAHOO.log(("xy: " + [x, y]), "iframe");
 
2866
 
 
2867
            this.cfg.refireEvent("iframe");
 
2868
            this.moveEvent.fire([x, y]);
 
2869
        },
 
2870
 
 
2871
        /**
 
2872
        * The default event handler fired when the "x" property is changed.
 
2873
        * @method configX
 
2874
        * @param {String} type The CustomEvent type (usually the property name)
 
2875
        * @param {Object[]} args The CustomEvent arguments. For configuration 
 
2876
        * handlers, args[0] will equal the newly applied value for the property.
 
2877
        * @param {Object} obj The scope object. For configuration handlers, 
 
2878
        * this will usually equal the owner.
 
2879
        */
 
2880
        configX: function (type, args, obj) {
 
2881
 
 
2882
            var x = args[0],
 
2883
                y = this.cfg.getProperty("y");
 
2884
 
 
2885
            this.cfg.setProperty("x", x, true);
 
2886
            this.cfg.setProperty("y", y, true);
 
2887
 
 
2888
            this.beforeMoveEvent.fire([x, y]);
 
2889
 
 
2890
            x = this.cfg.getProperty("x");
 
2891
            y = this.cfg.getProperty("y");
 
2892
            
 
2893
            Dom.setX(this.element, x, true);
 
2894
 
 
2895
            this.cfg.setProperty("xy", [x, y], true);
 
2896
 
 
2897
            this.cfg.refireEvent("iframe");
 
2898
            this.moveEvent.fire([x, y]);
 
2899
        },
 
2900
 
 
2901
        /**
 
2902
        * The default event handler fired when the "y" property is changed.
 
2903
        * @method configY
 
2904
        * @param {String} type The CustomEvent type (usually the property name)
 
2905
        * @param {Object[]} args The CustomEvent arguments. For configuration 
 
2906
        * handlers, args[0] will equal the newly applied value for the property.
 
2907
        * @param {Object} obj The scope object. For configuration handlers, 
 
2908
        * this will usually equal the owner.
 
2909
        */
 
2910
        configY: function (type, args, obj) {
 
2911
 
 
2912
            var x = this.cfg.getProperty("x"),
 
2913
                y = args[0];
 
2914
 
 
2915
            this.cfg.setProperty("x", x, true);
 
2916
            this.cfg.setProperty("y", y, true);
 
2917
 
 
2918
            this.beforeMoveEvent.fire([x, y]);
 
2919
 
 
2920
            x = this.cfg.getProperty("x");
 
2921
            y = this.cfg.getProperty("y");
 
2922
 
 
2923
            Dom.setY(this.element, y, true);
 
2924
 
 
2925
            this.cfg.setProperty("xy", [x, y], true);
 
2926
 
 
2927
            this.cfg.refireEvent("iframe");
 
2928
            this.moveEvent.fire([x, y]);
 
2929
        },
 
2930
        
 
2931
        /**
 
2932
        * Shows the iframe shim, if it has been enabled.
 
2933
        * @method showIframe
 
2934
        */
 
2935
        showIframe: function () {
 
2936
 
 
2937
            var oIFrame = this.iframe,
 
2938
                oParentNode;
 
2939
 
 
2940
            if (oIFrame) {
 
2941
                oParentNode = this.element.parentNode;
 
2942
 
 
2943
                if (oParentNode != oIFrame.parentNode) {
 
2944
                    this._addToParent(oParentNode, oIFrame);
 
2945
                }
 
2946
                oIFrame.style.display = "block";
 
2947
            }
 
2948
        },
 
2949
 
 
2950
        /**
 
2951
        * Hides the iframe shim, if it has been enabled.
 
2952
        * @method hideIframe
 
2953
        */
 
2954
        hideIframe: function () {
 
2955
            if (this.iframe) {
 
2956
                this.iframe.style.display = "none";
 
2957
            }
 
2958
        },
 
2959
 
 
2960
        /**
 
2961
        * Syncronizes the size and position of iframe shim to that of its 
 
2962
        * corresponding Overlay instance.
 
2963
        * @method syncIframe
 
2964
        */
 
2965
        syncIframe: function () {
 
2966
 
 
2967
            var oIFrame = this.iframe,
 
2968
                oElement = this.element,
 
2969
                nOffset = Overlay.IFRAME_OFFSET,
 
2970
                nDimensionOffset = (nOffset * 2),
 
2971
                aXY;
 
2972
 
 
2973
            if (oIFrame) {
 
2974
                // Size <iframe>
 
2975
                oIFrame.style.width = (oElement.offsetWidth + nDimensionOffset + "px");
 
2976
                oIFrame.style.height = (oElement.offsetHeight + nDimensionOffset + "px");
 
2977
 
 
2978
                // Position <iframe>
 
2979
                aXY = this.cfg.getProperty("xy");
 
2980
 
 
2981
                if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
 
2982
                    this.syncPosition();
 
2983
                    aXY = this.cfg.getProperty("xy");
 
2984
                }
 
2985
                Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
 
2986
            }
 
2987
        },
 
2988
 
 
2989
        /**
 
2990
         * Sets the zindex of the iframe shim, if it exists, based on the zindex of
 
2991
         * the Overlay element. The zindex of the iframe is set to be one less 
 
2992
         * than the Overlay element's zindex.
 
2993
         * 
 
2994
         * <p>NOTE: This method will not bump up the zindex of the Overlay element
 
2995
         * to ensure that the iframe shim has a non-negative zindex.
 
2996
         * If you require the iframe zindex to be 0 or higher, the zindex of 
 
2997
         * the Overlay element should be set to a value greater than 0, before 
 
2998
         * this method is called.
 
2999
         * </p>
 
3000
         * @method stackIframe
 
3001
         */
 
3002
        stackIframe: function () {
 
3003
            if (this.iframe) {
 
3004
                var overlayZ = Dom.getStyle(this.element, "zIndex");
 
3005
                if (!YAHOO.lang.isUndefined(overlayZ) && !isNaN(overlayZ)) {
 
3006
                    Dom.setStyle(this.iframe, "zIndex", (overlayZ - 1));
 
3007
                }
 
3008
            }
 
3009
        },
 
3010
 
 
3011
        /**
 
3012
        * The default event handler fired when the "iframe" property is changed.
 
3013
        * @method configIframe
 
3014
        * @param {String} type The CustomEvent type (usually the property name)
 
3015
        * @param {Object[]} args The CustomEvent arguments. For configuration 
 
3016
        * handlers, args[0] will equal the newly applied value for the property.
 
3017
        * @param {Object} obj The scope object. For configuration handlers, 
 
3018
        * this will usually equal the owner.
 
3019
        */
 
3020
        configIframe: function (type, args, obj) {
 
3021
 
 
3022
            var bIFrame = args[0];
 
3023
 
 
3024
            function createIFrame() {
 
3025
 
 
3026
                var oIFrame = this.iframe,
 
3027
                    oElement = this.element,
 
3028
                    oParent;
 
3029
 
 
3030
                if (!oIFrame) {
 
3031
                    if (!m_oIFrameTemplate) {
 
3032
                        m_oIFrameTemplate = document.createElement("iframe");
 
3033
 
 
3034
                        if (this.isSecure) {
 
3035
                            m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
 
3036
                        }
 
3037
 
 
3038
                        /*
 
3039
                            Set the opacity of the <iframe> to 0 so that it 
 
3040
                            doesn't modify the opacity of any transparent 
 
3041
                            elements that may be on top of it (like a shadow).
 
3042
                        */
 
3043
                        if (UA.ie) {
 
3044
                            m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
 
3045
                            /*
 
3046
                                 Need to set the "frameBorder" property to 0 
 
3047
                                 supress the default <iframe> border in IE.  
 
3048
                                 Setting the CSS "border" property alone 
 
3049
                                 doesn't supress it.
 
3050
                            */
 
3051
                            m_oIFrameTemplate.frameBorder = 0;
 
3052
                        }
 
3053
                        else {
 
3054
                            m_oIFrameTemplate.style.opacity = "0";
 
3055
                        }
 
3056
 
 
3057
                        m_oIFrameTemplate.style.position = "absolute";
 
3058
                        m_oIFrameTemplate.style.border = "none";
 
3059
                        m_oIFrameTemplate.style.margin = "0";
 
3060
                        m_oIFrameTemplate.style.padding = "0";
 
3061
                        m_oIFrameTemplate.style.display = "none";
 
3062
                    }
 
3063
 
 
3064
                    oIFrame = m_oIFrameTemplate.cloneNode(false);
 
3065
                    oParent = oElement.parentNode;
 
3066
 
 
3067
                    var parentNode = oParent || document.body;
 
3068
 
 
3069
                    this._addToParent(parentNode, oIFrame);
 
3070
                    this.iframe = oIFrame;
 
3071
                }
 
3072
 
 
3073
                /*
 
3074
                     Show the <iframe> before positioning it since the "setXY" 
 
3075
                     method of DOM requires the element be in the document 
 
3076
                     and visible.
 
3077
                */
 
3078
                this.showIframe();
 
3079
 
 
3080
                /*
 
3081
                     Syncronize the size and position of the <iframe> to that 
 
3082
                     of the Overlay.
 
3083
                */
 
3084
                this.syncIframe();
 
3085
                this.stackIframe();
 
3086
 
 
3087
                // Add event listeners to update the <iframe> when necessary
 
3088
                if (!this._hasIframeEventListeners) {
 
3089
                    this.showEvent.subscribe(this.showIframe);
 
3090
                    this.hideEvent.subscribe(this.hideIframe);
 
3091
                    this.changeContentEvent.subscribe(this.syncIframe);
 
3092
 
 
3093
                    this._hasIframeEventListeners = true;
 
3094
                }
 
3095
            }
 
3096
 
 
3097
            function onBeforeShow() {
 
3098
                createIFrame.call(this);
 
3099
                this.beforeShowEvent.unsubscribe(onBeforeShow);
 
3100
                this._iframeDeferred = false;
 
3101
            }
 
3102
 
 
3103
            if (bIFrame) { // <iframe> shim is enabled
 
3104
 
 
3105
                if (this.cfg.getProperty("visible")) {
 
3106
                    createIFrame.call(this);
 
3107
                } else {
 
3108
                    if (!this._iframeDeferred) {
 
3109
                        this.beforeShowEvent.subscribe(onBeforeShow);
 
3110
                        this._iframeDeferred = true;
 
3111
                    }
 
3112
                }
 
3113
 
 
3114
            } else {    // <iframe> shim is disabled
 
3115
                this.hideIframe();
 
3116
 
 
3117
                if (this._hasIframeEventListeners) {
 
3118
                    this.showEvent.unsubscribe(this.showIframe);
 
3119
                    this.hideEvent.unsubscribe(this.hideIframe);
 
3120
                    this.changeContentEvent.unsubscribe(this.syncIframe);
 
3121
 
 
3122
                    this._hasIframeEventListeners = false;
 
3123
                }
 
3124
            }
 
3125
        },
 
3126
 
 
3127
        /**
 
3128
         * Set's the container's XY value from DOM if not already set.
 
3129
         * 
 
3130
         * Differs from syncPosition, in that the XY value is only sync'd with DOM if 
 
3131
         * not already set. The method also refire's the XY config property event, so any
 
3132
         * beforeMove, Move event listeners are invoked.
 
3133
         * 
 
3134
         * @method _primeXYFromDOM
 
3135
         * @protected
 
3136
         */
 
3137
        _primeXYFromDOM : function() {
 
3138
            if (YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))) {
 
3139
                // Set CFG XY based on DOM XY
 
3140
                this.syncPosition();
 
3141
                // Account for XY being set silently in syncPosition (no moveTo fired/called)
 
3142
                this.cfg.refireEvent("xy");
 
3143
                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
 
3144
            }
 
3145
        },
 
3146
 
 
3147
        /**
 
3148
        * The default event handler fired when the "constraintoviewport" 
 
3149
        * property is changed.
 
3150
        * @method configConstrainToViewport
 
3151
        * @param {String} type The CustomEvent type (usually the property name)
 
3152
        * @param {Object[]} args The CustomEvent arguments. For configuration 
 
3153
        * handlers, args[0] will equal the newly applied value for 
 
3154
        * the property.
 
3155
        * @param {Object} obj The scope object. For configuration handlers, 
 
3156
        * this will usually equal the owner.
 
3157
        */
 
3158
        configConstrainToViewport: function (type, args, obj) {
 
3159
            var val = args[0];
 
3160
 
 
3161
            if (val) {
 
3162
                if (! Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
 
3163
                    this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
 
3164
                }
 
3165
                if (! Config.alreadySubscribed(this.beforeShowEvent, this._primeXYFromDOM)) {
 
3166
                    this.beforeShowEvent.subscribe(this._primeXYFromDOM);
 
3167
                }
 
3168
            } else {
 
3169
                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
 
3170
                this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
 
3171
            }
 
3172
        },
 
3173
 
 
3174
         /**
 
3175
        * The default event handler fired when the "context" property
 
3176
        * is changed.
 
3177
        * 
 
3178
        * @method configContext
 
3179
        * @param {String} type The CustomEvent type (usually the property name)
 
3180
        * @param {Object[]} args The CustomEvent arguments. For configuration 
 
3181
        * handlers, args[0] will equal the newly applied value for the property.
 
3182
        * @param {Object} obj The scope object. For configuration handlers, 
 
3183
        * this will usually equal the owner.
 
3184
        */
 
3185
        configContext: function (type, args, obj) {
 
3186
 
 
3187
            var contextArgs = args[0],
 
3188
                contextEl,
 
3189
                elementMagnetCorner,
 
3190
                contextMagnetCorner,
 
3191
                triggers,
 
3192
                defTriggers = this.CONTEXT_TRIGGERS;
 
3193
 
 
3194
            if (contextArgs) {
 
3195
 
 
3196
                contextEl = contextArgs[0];
 
3197
                elementMagnetCorner = contextArgs[1];
 
3198
                contextMagnetCorner = contextArgs[2];
 
3199
                triggers = contextArgs[3];
 
3200
 
 
3201
                if (defTriggers && defTriggers.length > 0) {
 
3202
                    triggers = (triggers || []).concat(defTriggers);
 
3203
                }
 
3204
 
 
3205
                if (contextEl) {
 
3206
                    if (typeof contextEl == "string") {
 
3207
                        this.cfg.setProperty("context", [
 
3208
                                document.getElementById(contextEl), 
 
3209
                                elementMagnetCorner,
 
3210
                                contextMagnetCorner,
 
3211
                                triggers ],
 
3212
                                true);
 
3213
                    }
 
3214
 
 
3215
                    if (elementMagnetCorner && contextMagnetCorner) {
 
3216
                        this.align(elementMagnetCorner, contextMagnetCorner);
 
3217
                    }
 
3218
 
 
3219
                    if (this._contextTriggers) {
 
3220
                        // Unsubscribe Old Set
 
3221
                        this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
 
3222
                    }
 
3223
 
 
3224
                    if (triggers) {
 
3225
                        // Subscribe New Set
 
3226
                        this._processTriggers(triggers, _SUBSCRIBE, this._alignOnTrigger);
 
3227
                        this._contextTriggers = triggers;
 
3228
                    }
 
3229
                }
 
3230
            }
 
3231
        },
 
3232
 
 
3233
        /**
 
3234
         * Custom Event handler for context alignment triggers. Invokes the align method
 
3235
         * 
 
3236
         * @method _alignOnTrigger
 
3237
         * @protected
 
3238
         * 
 
3239
         * @param {String} type The event type (not used by the default implementation)
 
3240
         * @param {Any[]} args The array of arguments for the trigger event (not used by the default implementation)
 
3241
         */
 
3242
        _alignOnTrigger: function(type, args) {
 
3243
            this.align();
 
3244
        },
 
3245
 
 
3246
        /**
 
3247
         * Helper method to locate the custom event instance for the event name string
 
3248
         * passed in. As a convenience measure, any custom events passed in are returned.
 
3249
         *
 
3250
         * @method _findTriggerCE
 
3251
         * @private
 
3252
         *
 
3253
         * @param {String|CustomEvent} t Either a CustomEvent, or event type (e.g. "windowScroll") for which a 
 
3254
         * custom event instance needs to be looked up from the Overlay._TRIGGER_MAP.
 
3255
         */
 
3256
        _findTriggerCE : function(t) {
 
3257
            var tce = null;
 
3258
            if (t instanceof CustomEvent) {
 
3259
                tce = t;
 
3260
            } else if (Overlay._TRIGGER_MAP[t]) {
 
3261
                tce = Overlay._TRIGGER_MAP[t];
 
3262
            }
 
3263
            return tce;
 
3264
        },
 
3265
 
 
3266
        /**
 
3267
         * Utility method that subscribes or unsubscribes the given 
 
3268
         * function from the list of trigger events provided.
 
3269
         *
 
3270
         * @method _processTriggers
 
3271
         * @protected 
 
3272
         *
 
3273
         * @param {Array[String|CustomEvent]} triggers An array of either CustomEvents, event type strings 
 
3274
         * (e.g. "beforeShow", "windowScroll") to/from which the provided function should be 
 
3275
         * subscribed/unsubscribed respectively.
 
3276
         *
 
3277
         * @param {String} mode Either "subscribe" or "unsubscribe", specifying whether or not
 
3278
         * we are subscribing or unsubscribing trigger listeners
 
3279
         * 
 
3280
         * @param {Function} fn The function to be subscribed/unsubscribed to/from the trigger event.
 
3281
         * Context is always set to the overlay instance, and no additional object argument 
 
3282
         * get passed to the subscribed function.
 
3283
         */
 
3284
        _processTriggers : function(triggers, mode, fn) {
 
3285
            var t, tce;
 
3286
 
 
3287
            for (var i = 0, l = triggers.length; i < l; ++i) {
 
3288
                t = triggers[i];
 
3289
                tce = this._findTriggerCE(t);
 
3290
                if (tce) {
 
3291
                    tce[mode](fn, this, true);
 
3292
                } else {
 
3293
                    this[mode](t, fn);
 
3294
                }
 
3295
            }
 
3296
        },
 
3297
 
 
3298
        // END BUILT-IN PROPERTY EVENT HANDLERS //
 
3299
        /**
 
3300
        * Aligns the Overlay to its context element using the specified corner 
 
3301
        * points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, 
 
3302
        * and BOTTOM_RIGHT.
 
3303
        * @method align
 
3304
        * @param {String} elementAlign  The String representing the corner of 
 
3305
        * the Overlay that should be aligned to the context element
 
3306
        * @param {String} contextAlign  The corner of the context element 
 
3307
        * that the elementAlign corner should stick to.
 
3308
        */
 
3309
        align: function (elementAlign, contextAlign) {
 
3310
 
 
3311
            var contextArgs = this.cfg.getProperty("context"),
 
3312
                me = this,
 
3313
                context,
 
3314
                element,
 
3315
                contextRegion;
 
3316
 
 
3317
            function doAlign(v, h) {
 
3318
    
 
3319
                switch (elementAlign) {
 
3320
    
 
3321
                case Overlay.TOP_LEFT:
 
3322
                    me.moveTo(h, v);
 
3323
                    break;
 
3324
    
 
3325
                case Overlay.TOP_RIGHT:
 
3326
                    me.moveTo((h - element.offsetWidth), v);
 
3327
                    break;
 
3328
    
 
3329
                case Overlay.BOTTOM_LEFT:
 
3330
                    me.moveTo(h, (v - element.offsetHeight));
 
3331
                    break;
 
3332
    
 
3333
                case Overlay.BOTTOM_RIGHT:
 
3334
                    me.moveTo((h - element.offsetWidth), 
 
3335
                        (v - element.offsetHeight));
 
3336
                    break;
 
3337
                }
 
3338
            }
 
3339
    
 
3340
    
 
3341
            if (contextArgs) {
 
3342
            
 
3343
                context = contextArgs[0];
 
3344
                element = this.element;
 
3345
                me = this;
 
3346
                
 
3347
                if (! elementAlign) {
 
3348
                    elementAlign = contextArgs[1];
 
3349
                }
 
3350
                
 
3351
                if (! contextAlign) {
 
3352
                    contextAlign = contextArgs[2];
 
3353
                }
 
3354
                
 
3355
                if (element && context) {
 
3356
                    contextRegion = Dom.getRegion(context);
 
3357
 
 
3358
                    switch (contextAlign) {
 
3359
    
 
3360
                    case Overlay.TOP_LEFT:
 
3361
                        doAlign(contextRegion.top, contextRegion.left);
 
3362
                        break;
 
3363
    
 
3364
                    case Overlay.TOP_RIGHT:
 
3365
                        doAlign(contextRegion.top, contextRegion.right);
 
3366
                        break;
 
3367
    
 
3368
                    case Overlay.BOTTOM_LEFT:
 
3369
                        doAlign(contextRegion.bottom, contextRegion.left);
 
3370
                        break;
 
3371
    
 
3372
                    case Overlay.BOTTOM_RIGHT:
 
3373
                        doAlign(contextRegion.bottom, contextRegion.right);
 
3374
                        break;
 
3375
                    }
 
3376
    
 
3377
                }
 
3378
    
 
3379
            }
 
3380
            
 
3381
        },
 
3382
 
 
3383
        /**
 
3384
        * The default event handler executed when the moveEvent is fired, if the 
 
3385
        * "constraintoviewport" is set to true.
 
3386
        * @method enforceConstraints
 
3387
        * @param {String} type The CustomEvent type (usually the property name)
 
3388
        * @param {Object[]} args The CustomEvent arguments. For configuration 
 
3389
        * handlers, args[0] will equal the newly applied value for the property.
 
3390
        * @param {Object} obj The scope object. For configuration handlers, 
 
3391
        * this will usually equal the owner.
 
3392
        */
 
3393
        enforceConstraints: function (type, args, obj) {
 
3394
            var pos = args[0];
 
3395
            
 
3396
            var cXY = this.getConstrainedXY(pos[0], pos[1]);
 
3397
            this.cfg.setProperty("x", cXY[0], true);
 
3398
            this.cfg.setProperty("y", cXY[1], true);
 
3399
            this.cfg.setProperty("xy", cXY, true);
 
3400
        },
 
3401
 
 
3402
 
 
3403
        /**
 
3404
         * Given x coordinate value, returns the calculated x coordinate required to 
 
3405
         * position the Overlay if it is to be constrained to the viewport, based on the 
 
3406
         * current element size, viewport dimensions and scroll values.
 
3407
         *
 
3408
         * @param {Number} x The X coordinate value to be constrained
 
3409
         * @return {Number} The constrained x coordinate
 
3410
         */             
 
3411
        getConstrainedX: function (x) {
 
3412
 
 
3413
            var oOverlay = this,
 
3414
                oOverlayEl = oOverlay.element,
 
3415
                nOverlayOffsetWidth = oOverlayEl.offsetWidth,
 
3416
 
 
3417
                nViewportOffset = Overlay.VIEWPORT_OFFSET,
 
3418
                viewPortWidth = Dom.getViewportWidth(),
 
3419
                scrollX = Dom.getDocumentScrollLeft(),
 
3420
 
 
3421
                bCanConstrain = (nOverlayOffsetWidth + nViewportOffset < viewPortWidth),
 
3422
 
 
3423
                aContext = this.cfg.getProperty("context"),
 
3424
                oContextEl,
 
3425
                nContextElX,
 
3426
                nContextElWidth,
 
3427
 
 
3428
                bFlipped = false,
 
3429
 
 
3430
                nLeftRegionWidth,
 
3431
                nRightRegionWidth,
 
3432
 
 
3433
                leftConstraint,
 
3434
                rightConstraint,
 
3435
 
 
3436
                xNew = x,
 
3437
 
 
3438
                oOverlapPositions = {
 
3439
 
 
3440
                    "tltr": true,
 
3441
                    "blbr": true,
 
3442
                    "brbl": true,
 
3443
                    "trtl": true
 
3444
                
 
3445
                };
 
3446
 
 
3447
 
 
3448
            var flipHorizontal = function () {
 
3449
            
 
3450
                var nNewX;
 
3451
            
 
3452
                if ((oOverlay.cfg.getProperty("x") - scrollX) > nContextElX) {
 
3453
                    nNewX = (nContextElX - nOverlayOffsetWidth);
 
3454
                }
 
3455
                else {
 
3456
                    nNewX = (nContextElX + nContextElWidth);
 
3457
                }
 
3458
                
 
3459
    
 
3460
                oOverlay.cfg.setProperty("x", (nNewX + scrollX), true);
 
3461
    
 
3462
                return nNewX;
 
3463
    
 
3464
            };
 
3465
 
 
3466
 
 
3467
 
 
3468
            /*
 
3469
                 Uses the context element's position to calculate the availble width 
 
3470
                 to the right and left of it to display its corresponding Overlay.
 
3471
            */
 
3472
 
 
3473
            var getDisplayRegionWidth = function () {
 
3474
 
 
3475
                // The Overlay is to the right of the context element
 
3476
 
 
3477
                if ((oOverlay.cfg.getProperty("x") - scrollX) > nContextElX) {
 
3478
                    return (nRightRegionWidth - nViewportOffset);
 
3479
                }
 
3480
                else {  // The Overlay is to the left of the context element
 
3481
                    return (nLeftRegionWidth - nViewportOffset);
 
3482
                }
 
3483
            
 
3484
            };
 
3485
    
 
3486
 
 
3487
            /*
 
3488
                Positions the Overlay to the left or right of the context element so that it remains 
 
3489
                inside the viewport.
 
3490
            */
 
3491
    
 
3492
            var setHorizontalPosition = function () {
 
3493
            
 
3494
                var nDisplayRegionWidth = getDisplayRegionWidth(),
 
3495
                    fnReturnVal;
 
3496
 
 
3497
                if (nOverlayOffsetWidth > nDisplayRegionWidth) {
 
3498
        
 
3499
                    if (bFlipped) {
 
3500
        
 
3501
                        /*
 
3502
                             All possible positions and values have been 
 
3503
                             tried, but none were successful, so fall back 
 
3504
                             to the original size and position.
 
3505
                        */
 
3506
    
 
3507
                        flipHorizontal();
 
3508
                        
 
3509
                    }
 
3510
                    else {
 
3511
        
 
3512
                        flipHorizontal();
 
3513
 
 
3514
                        bFlipped = true;
 
3515
        
 
3516
                        fnReturnVal = setHorizontalPosition();
 
3517
        
 
3518
                    }
 
3519
                
 
3520
                }
 
3521
        
 
3522
                return fnReturnVal;
 
3523
            
 
3524
            };
 
3525
 
 
3526
 
 
3527
            if (this.cfg.getProperty("preventcontextoverlap") && aContext && 
 
3528
                                oOverlapPositions[(aContext[1] + aContext[2])]) {
 
3529
 
 
3530
                if (bCanConstrain) {
 
3531
 
 
3532
                    oContextEl = aContext[0];
 
3533
                    nContextElX = Dom.getX(oContextEl) - scrollX;
 
3534
                    nContextElWidth = oContextEl.offsetWidth;
 
3535
                    nLeftRegionWidth = nContextElX;
 
3536
                    nRightRegionWidth = (viewPortWidth - (nContextElX + nContextElWidth));
 
3537
    
 
3538
                    setHorizontalPosition();
 
3539
 
 
3540
                }
 
3541
                
 
3542
                xNew = this.cfg.getProperty("x");
 
3543
            
 
3544
            }
 
3545
            else {
 
3546
 
 
3547
                if (bCanConstrain) {
 
3548
    
 
3549
                    leftConstraint = scrollX + nViewportOffset;
 
3550
                    rightConstraint = 
 
3551
                        scrollX + viewPortWidth - nOverlayOffsetWidth - nViewportOffset;
 
3552
    
 
3553
                    if (x < leftConstraint) {
 
3554
                        xNew = leftConstraint;
 
3555
                    } else if (x > rightConstraint) {
 
3556
                        xNew = rightConstraint;
 
3557
                    }
 
3558
                } else {
 
3559
                    xNew = nViewportOffset + scrollX;
 
3560
                }
 
3561
            
 
3562
            }
 
3563
 
 
3564
            return xNew;
 
3565
        
 
3566
        },
 
3567
 
 
3568
 
 
3569
        /**
 
3570
         * Given y coordinate value, returns the calculated y coordinate required to 
 
3571
         * position the Overlay if it is to be constrained to the viewport, based on the 
 
3572
         * current element size, viewport dimensions and scroll values.
 
3573
         *
 
3574
         * @param {Number} y The Y coordinate value to be constrained
 
3575
         * @return {Number} The constrained y coordinate
 
3576
         */             
 
3577
        getConstrainedY: function (y) {
 
3578
 
 
3579
            var oOverlay = this,
 
3580
                oOverlayEl = oOverlay.element,
 
3581
                nOverlayOffsetHeight = oOverlayEl.offsetHeight,
 
3582
            
 
3583
                nViewportOffset = Overlay.VIEWPORT_OFFSET,
 
3584
                viewPortHeight = Dom.getViewportHeight(),
 
3585
                scrollY = Dom.getDocumentScrollTop(),
 
3586
 
 
3587
                bCanConstrain = (nOverlayOffsetHeight + nViewportOffset < viewPortHeight),
 
3588
 
 
3589
                aContext = this.cfg.getProperty("context"),
 
3590
                oContextEl,
 
3591
                nContextElY,
 
3592
                nContextElHeight,
 
3593
 
 
3594
                bFlipped = false,
 
3595
 
 
3596
                nTopRegionHeight,
 
3597
                nBottomRegionHeight,
 
3598
 
 
3599
                topConstraint,
 
3600
                bottomConstraint,
 
3601
 
 
3602
                yNew = y,
 
3603
                
 
3604
                oOverlapPositions = {
 
3605
                    "trbr": true,
 
3606
                    "tlbl": true,
 
3607
                    "bltl": true,
 
3608
                    "brtr": true
 
3609
                };
 
3610
 
 
3611
 
 
3612
            var flipVertical = function () {
 
3613
 
 
3614
                var nNewY;
 
3615
            
 
3616
                // The Overlay is below the context element, flip it above
 
3617
                if ((oOverlay.cfg.getProperty("y") - scrollY) > nContextElY) { 
 
3618
                    nNewY = (nContextElY - nOverlayOffsetHeight);
 
3619
                }
 
3620
                else {  // The Overlay is above the context element, flip it below
 
3621
                    nNewY = (nContextElY + nContextElHeight);
 
3622
                }
 
3623
    
 
3624
                oOverlay.cfg.setProperty("y", (nNewY + scrollY), true);
 
3625
                
 
3626
                return nNewY;
 
3627
            
 
3628
            };
 
3629
 
 
3630
 
 
3631
            /*
 
3632
                 Uses the context element's position to calculate the availble height 
 
3633
                 above and below it to display its corresponding Overlay.
 
3634
            */
 
3635
 
 
3636
            var getDisplayRegionHeight = function () {
 
3637
 
 
3638
                // The Overlay is below the context element
 
3639
                if ((oOverlay.cfg.getProperty("y") - scrollY) > nContextElY) {
 
3640
                    return (nBottomRegionHeight - nViewportOffset);                             
 
3641
                }
 
3642
                else {  // The Overlay is above the context element
 
3643
                    return (nTopRegionHeight - nViewportOffset);                                
 
3644
                }
 
3645
        
 
3646
            };
 
3647
 
 
3648
 
 
3649
            /*
 
3650
                Trys to place the Overlay in the best possible position (either above or 
 
3651
                below its corresponding context element).
 
3652
            */
 
3653
        
 
3654
            var setVerticalPosition = function () {
 
3655
        
 
3656
                var nDisplayRegionHeight = getDisplayRegionHeight(),
 
3657
                    fnReturnVal;
 
3658
                    
 
3659
 
 
3660
                if (nOverlayOffsetHeight > nDisplayRegionHeight) {
 
3661
                   
 
3662
                    if (bFlipped) {
 
3663
        
 
3664
                        /*
 
3665
                             All possible positions and values for the 
 
3666
                             "maxheight" configuration property have been 
 
3667
                             tried, but none were successful, so fall back 
 
3668
                             to the original size and position.
 
3669
                        */
 
3670
    
 
3671
                        flipVertical();
 
3672
                        
 
3673
                    }
 
3674
                    else {
 
3675
        
 
3676
                        flipVertical();
 
3677
 
 
3678
                        bFlipped = true;
 
3679
        
 
3680
                        fnReturnVal = setVerticalPosition();
 
3681
        
 
3682
                    }
 
3683
                
 
3684
                }
 
3685
        
 
3686
                return fnReturnVal;
 
3687
        
 
3688
            };
 
3689
 
 
3690
 
 
3691
            if (this.cfg.getProperty("preventcontextoverlap") && aContext && 
 
3692
                oOverlapPositions[(aContext[1] + aContext[2])]) {
 
3693
 
 
3694
                if (bCanConstrain) {
 
3695
 
 
3696
                    oContextEl = aContext[0];
 
3697
                    nContextElHeight = oContextEl.offsetHeight;
 
3698
                    nContextElY = (Dom.getY(oContextEl) - scrollY);
 
3699
    
 
3700
                    nTopRegionHeight = nContextElY;
 
3701
                    nBottomRegionHeight = (viewPortHeight - (nContextElY + nContextElHeight));
 
3702
    
 
3703
                    setVerticalPosition();
 
3704
                
 
3705
                }
 
3706
 
 
3707
                yNew = oOverlay.cfg.getProperty("y");
 
3708
 
 
3709
            }
 
3710
            else {
 
3711
 
 
3712
                if (bCanConstrain) {
 
3713
    
 
3714
                    topConstraint = scrollY + nViewportOffset;
 
3715
                    bottomConstraint = 
 
3716
                        scrollY + viewPortHeight - nOverlayOffsetHeight - nViewportOffset;
 
3717
    
 
3718
                    if (y < topConstraint) {
 
3719
                        yNew  = topConstraint;
 
3720
                    } else if (y  > bottomConstraint) {
 
3721
                        yNew  = bottomConstraint;
 
3722
                    }
 
3723
                } else {
 
3724
                    yNew = nViewportOffset + scrollY;
 
3725
                }
 
3726
 
 
3727
            }
 
3728
 
 
3729
            return yNew;
 
3730
        },
 
3731
 
 
3732
 
 
3733
        /**
 
3734
         * Given x, y coordinate values, returns the calculated coordinates required to 
 
3735
         * position the Overlay if it is to be constrained to the viewport, based on the 
 
3736
         * current element size, viewport dimensions and scroll values.
 
3737
         *
 
3738
         * @param {Number} x The X coordinate value to be constrained
 
3739
         * @param {Number} y The Y coordinate value to be constrained
 
3740
         * @return {Array} The constrained x and y coordinates at index 0 and 1 respectively;
 
3741
         */
 
3742
        getConstrainedXY: function(x, y) {
 
3743
            return [this.getConstrainedX(x), this.getConstrainedY(y)];
 
3744
        },
 
3745
 
 
3746
        /**
 
3747
        * Centers the container in the viewport.
 
3748
        * @method center
 
3749
        */
 
3750
        center: function () {
 
3751
 
 
3752
            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
 
3753
                elementWidth = this.element.offsetWidth,
 
3754
                elementHeight = this.element.offsetHeight,
 
3755
                viewPortWidth = Dom.getViewportWidth(),
 
3756
                viewPortHeight = Dom.getViewportHeight(),
 
3757
                x,
 
3758
                y;
 
3759
 
 
3760
            if (elementWidth < viewPortWidth) {
 
3761
                x = (viewPortWidth / 2) - (elementWidth / 2) + Dom.getDocumentScrollLeft();
 
3762
            } else {
 
3763
                x = nViewportOffset + Dom.getDocumentScrollLeft();
 
3764
            }
 
3765
 
 
3766
            if (elementHeight < viewPortHeight) {
 
3767
                y = (viewPortHeight / 2) - (elementHeight / 2) + Dom.getDocumentScrollTop();
 
3768
            } else {
 
3769
                y = nViewportOffset + Dom.getDocumentScrollTop();
 
3770
            }
 
3771
 
 
3772
            this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
 
3773
            this.cfg.refireEvent("iframe");
 
3774
        },
 
3775
 
 
3776
        /**
 
3777
        * Synchronizes the Panel's "xy", "x", and "y" properties with the 
 
3778
        * Panel's position in the DOM. This is primarily used to update  
 
3779
        * position information during drag & drop.
 
3780
        * @method syncPosition
 
3781
        */
 
3782
        syncPosition: function () {
 
3783
 
 
3784
            var pos = Dom.getXY(this.element);
 
3785
 
 
3786
            this.cfg.setProperty("x", pos[0], true);
 
3787
            this.cfg.setProperty("y", pos[1], true);
 
3788
            this.cfg.setProperty("xy", pos, true);
 
3789
 
 
3790
        },
 
3791
 
 
3792
        /**
 
3793
        * Event handler fired when the resize monitor element is resized.
 
3794
        * @method onDomResize
 
3795
        * @param {DOMEvent} e The resize DOM event
 
3796
        * @param {Object} obj The scope object
 
3797
        */
 
3798
        onDomResize: function (e, obj) {
 
3799
 
 
3800
            var me = this;
 
3801
 
 
3802
            Overlay.superclass.onDomResize.call(this, e, obj);
 
3803
 
 
3804
            setTimeout(function () {
 
3805
                me.syncPosition();
 
3806
                me.cfg.refireEvent("iframe");
 
3807
                me.cfg.refireEvent("context");
 
3808
            }, 0);
 
3809
        },
 
3810
 
 
3811
        /**
 
3812
         * Determines the content box height of the given element (height of the element, without padding or borders) in pixels.
 
3813
         *
 
3814
         * @method _getComputedHeight
 
3815
         * @private
 
3816
         * @param {HTMLElement} el The element for which the content height needs to be determined
 
3817
         * @return {Number} The content box height of the given element, or null if it could not be determined.
 
3818
         */
 
3819
        _getComputedHeight : (function() {
 
3820
 
 
3821
            if (document.defaultView && document.defaultView.getComputedStyle) {
 
3822
                return function(el) {
 
3823
                    var height = null;
 
3824
                    if (el.ownerDocument && el.ownerDocument.defaultView) {
 
3825
                        var computed = el.ownerDocument.defaultView.getComputedStyle(el, '');
 
3826
                        if (computed) {
 
3827
                            height = parseInt(computed.height, 10);
 
3828
                        }
 
3829
                    }
 
3830
                    return (Lang.isNumber(height)) ? height : null;
 
3831
                };
 
3832
            } else {
 
3833
                return function(el) {
 
3834
                    var height = null;
 
3835
                    if (el.style.pixelHeight) {
 
3836
                        height = el.style.pixelHeight;
 
3837
                    }
 
3838
                    return (Lang.isNumber(height)) ? height : null;
 
3839
                };
 
3840
            }
 
3841
        })(),
 
3842
 
 
3843
        /**
 
3844
         * autofillheight validator. Verifies that the autofill value is either null 
 
3845
         * or one of the strings : "body", "header" or "footer".
 
3846
         *
 
3847
         * @method _validateAutoFillHeight
 
3848
         * @protected
 
3849
         * @param {String} val
 
3850
         * @return true, if valid, false otherwise
 
3851
         */
 
3852
        _validateAutoFillHeight : function(val) {
 
3853
            return (!val) || (Lang.isString(val) && Overlay.STD_MOD_RE.test(val));
 
3854
        },
 
3855
 
 
3856
        /**
 
3857
         * The default custom event handler executed when the overlay's height is changed, 
 
3858
         * if the autofillheight property has been set.
 
3859
         *
 
3860
         * @method _autoFillOnHeightChange
 
3861
         * @protected
 
3862
         * @param {String} type The event type
 
3863
         * @param {Array} args The array of arguments passed to event subscribers
 
3864
         * @param {HTMLElement} el The header, body or footer element which is to be resized to fill
 
3865
         * out the containers height
 
3866
         */
 
3867
        _autoFillOnHeightChange : function(type, args, el) {
 
3868
            this.fillHeight(el);
 
3869
        },
 
3870
 
 
3871
        /**
 
3872
         * Returns the sub-pixel height of the el, using getBoundingClientRect, if available,
 
3873
         * otherwise returns the offsetHeight
 
3874
         * @method _getPreciseHeight
 
3875
         * @private
 
3876
         * @param {HTMLElement} el
 
3877
         * @return {Float} The sub-pixel height if supported by the browser, else the rounded height.
 
3878
         */
 
3879
        _getPreciseHeight : function(el) {
 
3880
            var height = el.offsetHeight;
 
3881
 
 
3882
            if (el.getBoundingClientRect) {
 
3883
                var rect = el.getBoundingClientRect();
 
3884
                height = rect.bottom - rect.top;
 
3885
            }
 
3886
 
 
3887
            return height;
 
3888
        },
 
3889
 
 
3890
        /**
 
3891
         * <p>
 
3892
         * Sets the height on the provided header, body or footer element to 
 
3893
         * fill out the height of the container. It determines the height of the 
 
3894
         * containers content box, based on it's configured height value, and 
 
3895
         * sets the height of the autofillheight element to fill out any 
 
3896
         * space remaining after the other standard module element heights 
 
3897
         * have been accounted for.
 
3898
         * </p>
 
3899
         * <p><strong>NOTE:</strong> This method is not designed to work if an explicit 
 
3900
         * height has not been set on the container, since for an "auto" height container, 
 
3901
         * the heights of the header/body/footer will drive the height of the container.</p>
 
3902
         *
 
3903
         * @method fillHeight
 
3904
         * @param {HTMLElement} el The element which should be resized to fill out the height
 
3905
         * of the container element.
 
3906
         */
 
3907
        fillHeight : function(el) {
 
3908
            if (el) {
 
3909
                var container = this.innerElement || this.element,
 
3910
                    containerEls = [this.header, this.body, this.footer],
 
3911
                    containerEl,
 
3912
                    total = 0,
 
3913
                    filled = 0,
 
3914
                    remaining = 0,
 
3915
                    validEl = false;
 
3916
 
 
3917
                for (var i = 0, l = containerEls.length; i < l; i++) {
 
3918
                    containerEl = containerEls[i];
 
3919
                    if (containerEl) {
 
3920
                        if (el !== containerEl) {
 
3921
                            filled += this._getPreciseHeight(containerEl);
 
3922
                        } else {
 
3923
                            validEl = true;
 
3924
                        }
 
3925
                    }
 
3926
                }
 
3927
 
 
3928
                if (validEl) {
 
3929
 
 
3930
                    if (UA.ie || UA.opera) {
 
3931
                        // Need to set height to 0, to allow height to be reduced
 
3932
                        Dom.setStyle(el, 'height', 0 + 'px');
 
3933
                    }
 
3934
 
 
3935
                    total = this._getComputedHeight(container);
 
3936
 
 
3937
                    // Fallback, if we can't get computed value for content height
 
3938
                    if (total === null) {
 
3939
                        Dom.addClass(container, "yui-override-padding");
 
3940
                        total = container.clientHeight; // Content, No Border, 0 Padding (set by yui-override-padding)
 
3941
                        Dom.removeClass(container, "yui-override-padding");
 
3942
                    }
 
3943
    
 
3944
                    remaining = total - filled;
 
3945
    
 
3946
                    Dom.setStyle(el, "height", remaining + "px");
 
3947
    
 
3948
                    // Re-adjust height if required, to account for el padding and border
 
3949
                    if (el.offsetHeight != remaining) {
 
3950
                        remaining = remaining - (el.offsetHeight - remaining);
 
3951
                    }
 
3952
                    Dom.setStyle(el, "height", remaining + "px");
 
3953
                }
 
3954
            }
 
3955
        },
 
3956
 
 
3957
        /**
 
3958
        * Places the Overlay on top of all other instances of 
 
3959
        * YAHOO.widget.Overlay.
 
3960
        * @method bringToTop
 
3961
        */
 
3962
        bringToTop: function () {
 
3963
 
 
3964
            var aOverlays = [],
 
3965
                oElement = this.element;
 
3966
 
 
3967
            function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
 
3968
 
 
3969
                var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
 
3970
                    sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
 
3971
 
 
3972
                    nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 0 : parseInt(sZIndex1, 10),
 
3973
                    nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 0 : parseInt(sZIndex2, 10);
 
3974
 
 
3975
                if (nZIndex1 > nZIndex2) {
 
3976
                    return -1;
 
3977
                } else if (nZIndex1 < nZIndex2) {
 
3978
                    return 1;
 
3979
                } else {
 
3980
                    return 0;
 
3981
                }
 
3982
            }
 
3983
 
 
3984
            function isOverlayElement(p_oElement) {
 
3985
 
 
3986
                var isOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
 
3987
                    Panel = YAHOO.widget.Panel;
 
3988
 
 
3989
                if (isOverlay && !Dom.isAncestor(oElement, p_oElement)) {
 
3990
                    if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
 
3991
                        aOverlays[aOverlays.length] = p_oElement.parentNode;
 
3992
                    } else {
 
3993
                        aOverlays[aOverlays.length] = p_oElement;
 
3994
                    }
 
3995
                }
 
3996
            }
 
3997
 
 
3998
            Dom.getElementsBy(isOverlayElement, "DIV", document.body);
 
3999
 
 
4000
            aOverlays.sort(compareZIndexDesc);
 
4001
 
 
4002
            var oTopOverlay = aOverlays[0],
 
4003
                nTopZIndex;
 
4004
 
 
4005
            if (oTopOverlay) {
 
4006
                nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
 
4007
 
 
4008
                if (!isNaN(nTopZIndex)) {
 
4009
                    var bRequiresBump = false;
 
4010
 
 
4011
                    if (oTopOverlay != oElement) {
 
4012
                        bRequiresBump = true;
 
4013
                    } else if (aOverlays.length > 1) {
 
4014
                        var nNextZIndex = Dom.getStyle(aOverlays[1], "zIndex");
 
4015
                        // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
 
4016
                        if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
 
4017
                            bRequiresBump = true;
 
4018
                        }
 
4019
                    }
 
4020
                    if (bRequiresBump) {
 
4021
                        this.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
 
4022
                    }
 
4023
                }
 
4024
            }
 
4025
        },
 
4026
 
 
4027
        /**
 
4028
        * Removes the Overlay element from the DOM and sets all child 
 
4029
        * elements to null.
 
4030
        * @method destroy
 
4031
        */
 
4032
        destroy: function () {
 
4033
 
 
4034
            if (this.iframe) {
 
4035
                this.iframe.parentNode.removeChild(this.iframe);
 
4036
            }
 
4037
 
 
4038
            this.iframe = null;
 
4039
 
 
4040
            Overlay.windowResizeEvent.unsubscribe(
 
4041
                this.doCenterOnDOMEvent, this);
 
4042
    
 
4043
            Overlay.windowScrollEvent.unsubscribe(
 
4044
                this.doCenterOnDOMEvent, this);
 
4045
 
 
4046
            Module.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);
 
4047
 
 
4048
            Overlay.superclass.destroy.call(this);
 
4049
        },
 
4050
 
 
4051
        /**
 
4052
        * Returns a String representation of the object.
 
4053
        * @method toString
 
4054
        * @return {String} The string representation of the Overlay.
 
4055
        */
 
4056
        toString: function () {
 
4057
            return "Overlay " + this.id;
 
4058
        }
 
4059
 
 
4060
    });
 
4061
}());
 
4062
 
 
4063
(function () {
 
4064
 
 
4065
    /**
 
4066
    * OverlayManager is used for maintaining the focus status of 
 
4067
    * multiple Overlays.
 
4068
    * @namespace YAHOO.widget
 
4069
    * @namespace YAHOO.widget
 
4070
    * @class OverlayManager
 
4071
    * @constructor
 
4072
    * @param {Array} overlays Optional. A collection of Overlays to register 
 
4073
    * with the manager.
 
4074
    * @param {Object} userConfig  The object literal representing the user 
 
4075
    * configuration of the OverlayManager
 
4076
    */
 
4077
    YAHOO.widget.OverlayManager = function (userConfig) {
 
4078
        this.init(userConfig);
 
4079
    };
 
4080
 
 
4081
    var Overlay = YAHOO.widget.Overlay,
 
4082
        Event = YAHOO.util.Event,
 
4083
        Dom = YAHOO.util.Dom,
 
4084
        Config = YAHOO.util.Config,
 
4085
        CustomEvent = YAHOO.util.CustomEvent,
 
4086
        OverlayManager = YAHOO.widget.OverlayManager;
 
4087
 
 
4088
    /**
 
4089
    * The CSS class representing a focused Overlay
 
4090
    * @property OverlayManager.CSS_FOCUSED
 
4091
    * @static
 
4092
    * @final
 
4093
    * @type String
 
4094
    */
 
4095
    OverlayManager.CSS_FOCUSED = "focused";
 
4096
 
 
4097
    OverlayManager.prototype = {
 
4098
 
 
4099
        /**
 
4100
        * The class's constructor function
 
4101
        * @property contructor
 
4102
        * @type Function
 
4103
        */
 
4104
        constructor: OverlayManager,
 
4105
 
 
4106
        /**
 
4107
        * The array of Overlays that are currently registered
 
4108
        * @property overlays
 
4109
        * @type YAHOO.widget.Overlay[]
 
4110
        */
 
4111
        overlays: null,
 
4112
 
 
4113
        /**
 
4114
        * Initializes the default configuration of the OverlayManager
 
4115
        * @method initDefaultConfig
 
4116
        */
 
4117
        initDefaultConfig: function () {
 
4118
            /**
 
4119
            * The collection of registered Overlays in use by 
 
4120
            * the OverlayManager
 
4121
            * @config overlays
 
4122
            * @type YAHOO.widget.Overlay[]
 
4123
            * @default null
 
4124
            */
 
4125
            this.cfg.addProperty("overlays", { suppressEvent: true } );
 
4126
 
 
4127
            /**
 
4128
            * The default DOM event that should be used to focus an Overlay
 
4129
            * @config focusevent
 
4130
            * @type String
 
4131
            * @default "mousedown"
 
4132
            */
 
4133
            this.cfg.addProperty("focusevent", { value: "mousedown" } );
 
4134
        },
 
4135
 
 
4136
        /**
 
4137
        * Initializes the OverlayManager
 
4138
        * @method init
 
4139
        * @param {Overlay[]} overlays Optional. A collection of Overlays to 
 
4140
        * register with the manager.
 
4141
        * @param {Object} userConfig  The object literal representing the user 
 
4142
        * configuration of the OverlayManager
 
4143
        */
 
4144
        init: function (userConfig) {
 
4145
 
 
4146
            /**
 
4147
            * The OverlayManager's Config object used for monitoring 
 
4148
            * configuration properties.
 
4149
            * @property cfg
 
4150
            * @type Config
 
4151
            */
 
4152
            this.cfg = new Config(this);
 
4153
 
 
4154
            this.initDefaultConfig();
 
4155
 
 
4156
            if (userConfig) {
 
4157
                this.cfg.applyConfig(userConfig, true);
 
4158
            }
 
4159
            this.cfg.fireQueue();
 
4160
 
 
4161
            /**
 
4162
            * The currently activated Overlay
 
4163
            * @property activeOverlay
 
4164
            * @private
 
4165
            * @type YAHOO.widget.Overlay
 
4166
            */
 
4167
            var activeOverlay = null;
 
4168
 
 
4169
            /**
 
4170
            * Returns the currently focused Overlay
 
4171
            * @method getActive
 
4172
            * @return {Overlay} The currently focused Overlay
 
4173
            */
 
4174
            this.getActive = function () {
 
4175
                return activeOverlay;
 
4176
            };
 
4177
 
 
4178
            /**
 
4179
            * Focuses the specified Overlay
 
4180
            * @method focus
 
4181
            * @param {Overlay} overlay The Overlay to focus
 
4182
            * @param {String} overlay The id of the Overlay to focus
 
4183
            */
 
4184
            this.focus = function (overlay) {
 
4185
                var o = this.find(overlay);
 
4186
                if (o) {
 
4187
                    o.focus();
 
4188
                }
 
4189
            };
 
4190
 
 
4191
            /**
 
4192
            * Removes the specified Overlay from the manager
 
4193
            * @method remove
 
4194
            * @param {Overlay} overlay The Overlay to remove
 
4195
            * @param {String} overlay The id of the Overlay to remove
 
4196
            */
 
4197
            this.remove = function (overlay) {
 
4198
 
 
4199
                var o = this.find(overlay), 
 
4200
                        originalZ;
 
4201
 
 
4202
                if (o) {
 
4203
                    if (activeOverlay == o) {
 
4204
                        activeOverlay = null;
 
4205
                    }
 
4206
 
 
4207
                    var bDestroyed = (o.element === null && o.cfg === null) ? true : false;
 
4208
 
 
4209
                    if (!bDestroyed) {
 
4210
                        // Set it's zindex so that it's sorted to the end.
 
4211
                        originalZ = Dom.getStyle(o.element, "zIndex");
 
4212
                        o.cfg.setProperty("zIndex", -1000, true);
 
4213
                    }
 
4214
 
 
4215
                    this.overlays.sort(this.compareZIndexDesc);
 
4216
                    this.overlays = this.overlays.slice(0, (this.overlays.length - 1));
 
4217
 
 
4218
                    o.hideEvent.unsubscribe(o.blur);
 
4219
                    o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
 
4220
                    o.focusEvent.unsubscribe(this._onOverlayFocusHandler, o);
 
4221
                    o.blurEvent.unsubscribe(this._onOverlayBlurHandler, o);
 
4222
 
 
4223
                    if (!bDestroyed) {
 
4224
                        Event.removeListener(o.element, this.cfg.getProperty("focusevent"), this._onOverlayElementFocus);
 
4225
                        o.cfg.setProperty("zIndex", originalZ, true);
 
4226
                        o.cfg.setProperty("manager", null);
 
4227
                    }
 
4228
 
 
4229
                    /* _managed Flag for custom or existing. Don't want to remove existing */
 
4230
                    if (o.focusEvent._managed) { o.focusEvent = null; }
 
4231
                    if (o.blurEvent._managed) { o.blurEvent = null; }
 
4232
 
 
4233
                    if (o.focus._managed) { o.focus = null; }
 
4234
                    if (o.blur._managed) { o.blur = null; }
 
4235
                }
 
4236
            };
 
4237
 
 
4238
            /**
 
4239
            * Removes focus from all registered Overlays in the manager
 
4240
            * @method blurAll
 
4241
            */
 
4242
            this.blurAll = function () {
 
4243
 
 
4244
                var nOverlays = this.overlays.length,
 
4245
                    i;
 
4246
 
 
4247
                if (nOverlays > 0) {
 
4248
                    i = nOverlays - 1;
 
4249
                    do {
 
4250
                        this.overlays[i].blur();
 
4251
                    }
 
4252
                    while(i--);
 
4253
                }
 
4254
            };
 
4255
 
 
4256
            /**
 
4257
             * Updates the state of the OverlayManager and overlay, as a result of the overlay
 
4258
             * being blurred.
 
4259
             * 
 
4260
             * @method _manageBlur
 
4261
             * @param {Overlay} overlay The overlay instance which got blurred.
 
4262
             * @protected
 
4263
             */
 
4264
            this._manageBlur = function (overlay) {
 
4265
                var changed = false;
 
4266
                if (activeOverlay == overlay) {
 
4267
                    Dom.removeClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
 
4268
                    activeOverlay = null;
 
4269
                    changed = true;
 
4270
                }
 
4271
                return changed;
 
4272
            };
 
4273
 
 
4274
            /**
 
4275
             * Updates the state of the OverlayManager and overlay, as a result of the overlay 
 
4276
             * receiving focus.
 
4277
             *
 
4278
             * @method _manageFocus
 
4279
             * @param {Overlay} overlay The overlay instance which got focus.
 
4280
             * @protected
 
4281
             */
 
4282
            this._manageFocus = function(overlay) {
 
4283
                var changed = false;
 
4284
                if (activeOverlay != overlay) {
 
4285
                    if (activeOverlay) {
 
4286
                        activeOverlay.blur();
 
4287
                    }
 
4288
                    activeOverlay = overlay;
 
4289
                    this.bringToTop(activeOverlay);
 
4290
                    Dom.addClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
 
4291
                    changed = true;
 
4292
                }
 
4293
                return changed;
 
4294
            };
 
4295
 
 
4296
            var overlays = this.cfg.getProperty("overlays");
 
4297
 
 
4298
            if (! this.overlays) {
 
4299
                this.overlays = [];
 
4300
            }
 
4301
 
 
4302
            if (overlays) {
 
4303
                this.register(overlays);
 
4304
                this.overlays.sort(this.compareZIndexDesc);
 
4305
            }
 
4306
        },
 
4307
 
 
4308
        /**
 
4309
        * @method _onOverlayElementFocus
 
4310
        * @description Event handler for the DOM event that is used to focus 
 
4311
        * the Overlay instance as specified by the "focusevent" 
 
4312
        * configuration property.
 
4313
        * @private
 
4314
        * @param {Event} p_oEvent Object representing the DOM event 
 
4315
        * object passed back by the event utility (Event).
 
4316
        */
 
4317
        _onOverlayElementFocus: function (p_oEvent) {
 
4318
 
 
4319
            var oTarget = Event.getTarget(p_oEvent),
 
4320
                oClose = this.close;
 
4321
 
 
4322
            if (oClose && (oTarget == oClose || Dom.isAncestor(oClose, oTarget))) {
 
4323
                this.blur();
 
4324
            } else {
 
4325
                this.focus();
 
4326
            }
 
4327
        },
 
4328
 
 
4329
        /**
 
4330
        * @method _onOverlayDestroy
 
4331
        * @description "destroy" event handler for the Overlay.
 
4332
        * @private
 
4333
        * @param {String} p_sType String representing the name of the event  
 
4334
        * that was fired.
 
4335
        * @param {Array} p_aArgs Array of arguments sent when the event 
 
4336
        * was fired.
 
4337
        * @param {Overlay} p_oOverlay Object representing the overlay that 
 
4338
        * fired the event.
 
4339
        */
 
4340
        _onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
 
4341
            this.remove(p_oOverlay);
 
4342
        },
 
4343
 
 
4344
        /**
 
4345
        * @method _onOverlayFocusHandler
 
4346
        *
 
4347
        * focusEvent Handler, used to delegate to _manageFocus with the 
 
4348
        * correct arguments.
 
4349
        *
 
4350
        * @private
 
4351
        * @param {String} p_sType String representing the name of the event  
 
4352
        * that was fired.
 
4353
        * @param {Array} p_aArgs Array of arguments sent when the event 
 
4354
        * was fired.
 
4355
        * @param {Overlay} p_oOverlay Object representing the overlay that 
 
4356
        * fired the event.
 
4357
        */
 
4358
        _onOverlayFocusHandler: function(p_sType, p_aArgs, p_oOverlay) {
 
4359
            this._manageFocus(p_oOverlay);
 
4360
        },
 
4361
 
 
4362
        /**
 
4363
        * @method _onOverlayBlurHandler
 
4364
        *
 
4365
        * blurEvent Handler, used to delegate to _manageBlur with the 
 
4366
        * correct arguments.
 
4367
        *
 
4368
        * @private
 
4369
        * @param {String} p_sType String representing the name of the event  
 
4370
        * that was fired.
 
4371
        * @param {Array} p_aArgs Array of arguments sent when the event 
 
4372
        * was fired.
 
4373
        * @param {Overlay} p_oOverlay Object representing the overlay that 
 
4374
        * fired the event.
 
4375
        */
 
4376
        _onOverlayBlurHandler: function(p_sType, p_aArgs, p_oOverlay) {
 
4377
            this._manageBlur(p_oOverlay);
 
4378
        },
 
4379
 
 
4380
        /**
 
4381
         * Subscribes to the Overlay based instance focusEvent, to allow the OverlayManager to
 
4382
         * monitor focus state.
 
4383
         * 
 
4384
         * If the instance already has a focusEvent (e.g. Menu), OverlayManager will subscribe 
 
4385
         * to the existing focusEvent, however if a focusEvent or focus method does not exist
 
4386
         * on the instance, the _bindFocus method will add them, and the focus method will 
 
4387
         * update the OverlayManager's state directly.
 
4388
         * 
 
4389
         * @method _bindFocus
 
4390
         * @param {Overlay} overlay The overlay for which focus needs to be managed
 
4391
         * @protected
 
4392
         */
 
4393
        _bindFocus : function(overlay) {
 
4394
            var mgr = this;
 
4395
 
 
4396
            if (!overlay.focusEvent) {
 
4397
                overlay.focusEvent = overlay.createEvent("focus");
 
4398
                overlay.focusEvent.signature = CustomEvent.LIST;
 
4399
                overlay.focusEvent._managed = true;
 
4400
            } else {
 
4401
                overlay.focusEvent.subscribe(mgr._onOverlayFocusHandler, overlay, mgr);
 
4402
            }
 
4403
 
 
4404
            if (!overlay.focus) {
 
4405
                Event.on(overlay.element, mgr.cfg.getProperty("focusevent"), mgr._onOverlayElementFocus, null, overlay);
 
4406
                overlay.focus = function () {
 
4407
                    if (mgr._manageFocus(this)) {
 
4408
                        // For Panel/Dialog
 
4409
                        if (this.cfg.getProperty("visible") && this.focusFirst) {
 
4410
                            this.focusFirst();
 
4411
                        }
 
4412
                        this.focusEvent.fire();
 
4413
                    }
 
4414
                };
 
4415
                overlay.focus._managed = true;
 
4416
            }
 
4417
        },
 
4418
 
 
4419
        /**
 
4420
         * Subscribes to the Overlay based instance's blurEvent to allow the OverlayManager to
 
4421
         * monitor blur state.
 
4422
         *
 
4423
         * If the instance already has a blurEvent (e.g. Menu), OverlayManager will subscribe 
 
4424
         * to the existing blurEvent, however if a blurEvent or blur method does not exist
 
4425
         * on the instance, the _bindBlur method will add them, and the blur method 
 
4426
         * update the OverlayManager's state directly.
 
4427
         *
 
4428
         * @method _bindBlur
 
4429
         * @param {Overlay} overlay The overlay for which blur needs to be managed
 
4430
         * @protected
 
4431
         */
 
4432
        _bindBlur : function(overlay) {
 
4433
            var mgr = this;
 
4434
 
 
4435
            if (!overlay.blurEvent) {
 
4436
                overlay.blurEvent = overlay.createEvent("blur");
 
4437
                overlay.blurEvent.signature = CustomEvent.LIST;
 
4438
                overlay.focusEvent._managed = true;
 
4439
            } else {
 
4440
                overlay.blurEvent.subscribe(mgr._onOverlayBlurHandler, overlay, mgr);
 
4441
            }
 
4442
 
 
4443
            if (!overlay.blur) {
 
4444
                overlay.blur = function () {
 
4445
                    if (mgr._manageBlur(this)) {
 
4446
                        this.blurEvent.fire();
 
4447
                    }
 
4448
                };
 
4449
                overlay.blur._managed = true;
 
4450
            }
 
4451
 
 
4452
            overlay.hideEvent.subscribe(overlay.blur);
 
4453
        },
 
4454
 
 
4455
        /**
 
4456
         * Subscribes to the Overlay based instance's destroyEvent, to allow the Overlay
 
4457
         * to be removed for the OverlayManager when destroyed.
 
4458
         * 
 
4459
         * @method _bindDestroy
 
4460
         * @param {Overlay} overlay The overlay instance being managed
 
4461
         * @protected
 
4462
         */
 
4463
        _bindDestroy : function(overlay) {
 
4464
            var mgr = this;
 
4465
            overlay.destroyEvent.subscribe(mgr._onOverlayDestroy, overlay, mgr);
 
4466
        },
 
4467
 
 
4468
        /**
 
4469
         * Ensures the zIndex configuration property on the managed overlay based instance
 
4470
         * is set to the computed zIndex value from the DOM (with "auto" translating to 0).
 
4471
         *
 
4472
         * @method _syncZIndex
 
4473
         * @param {Overlay} overlay The overlay instance being managed
 
4474
         * @protected
 
4475
         */
 
4476
        _syncZIndex : function(overlay) {
 
4477
            var zIndex = Dom.getStyle(overlay.element, "zIndex");
 
4478
            if (!isNaN(zIndex)) {
 
4479
                overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
 
4480
            } else {
 
4481
                overlay.cfg.setProperty("zIndex", 0);
 
4482
            }
 
4483
        },
 
4484
 
 
4485
        /**
 
4486
        * Registers an Overlay or an array of Overlays with the manager. Upon 
 
4487
        * registration, the Overlay receives functions for focus and blur, 
 
4488
        * along with CustomEvents for each.
 
4489
        *
 
4490
        * @method register
 
4491
        * @param {Overlay} overlay  An Overlay to register with the manager.
 
4492
        * @param {Overlay[]} overlay  An array of Overlays to register with 
 
4493
        * the manager.
 
4494
        * @return {boolean} true if any Overlays are registered.
 
4495
        */
 
4496
        register: function (overlay) {
 
4497
 
 
4498
            var zIndex,
 
4499
                registered = false,
 
4500
                i,
 
4501
                n;
 
4502
 
 
4503
            if (overlay instanceof Overlay) {
 
4504
 
 
4505
                overlay.cfg.addProperty("manager", { value: this } );
 
4506
 
 
4507
                this._bindFocus(overlay);
 
4508
                this._bindBlur(overlay);
 
4509
                this._bindDestroy(overlay);
 
4510
                this._syncZIndex(overlay);
 
4511
 
 
4512
                this.overlays.push(overlay);
 
4513
                this.bringToTop(overlay);
 
4514
 
 
4515
                registered = true;
 
4516
 
 
4517
            } else if (overlay instanceof Array) {
 
4518
 
 
4519
                for (i = 0, n = overlay.length; i < n; i++) {
 
4520
                    registered = this.register(overlay[i]) || registered;
 
4521
                }
 
4522
 
 
4523
            }
 
4524
 
 
4525
            return registered;
 
4526
        },
 
4527
 
 
4528
        /**
 
4529
        * Places the specified Overlay instance on top of all other 
 
4530
        * Overlay instances.
 
4531
        * @method bringToTop
 
4532
        * @param {YAHOO.widget.Overlay} p_oOverlay Object representing an 
 
4533
        * Overlay instance.
 
4534
        * @param {String} p_oOverlay String representing the id of an 
 
4535
        * Overlay instance.
 
4536
        */        
 
4537
        bringToTop: function (p_oOverlay) {
 
4538
 
 
4539
            var oOverlay = this.find(p_oOverlay),
 
4540
                nTopZIndex,
 
4541
                oTopOverlay,
 
4542
                aOverlays;
 
4543
 
 
4544
            if (oOverlay) {
 
4545
 
 
4546
                aOverlays = this.overlays;
 
4547
                aOverlays.sort(this.compareZIndexDesc);
 
4548
 
 
4549
                oTopOverlay = aOverlays[0];
 
4550
 
 
4551
                if (oTopOverlay) {
 
4552
                    nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
 
4553
 
 
4554
                    if (!isNaN(nTopZIndex)) {
 
4555
 
 
4556
                        var bRequiresBump = false;
 
4557
 
 
4558
                        if (oTopOverlay !== oOverlay) {
 
4559
                            bRequiresBump = true;
 
4560
                        } else if (aOverlays.length > 1) {
 
4561
                            var nNextZIndex = Dom.getStyle(aOverlays[1].element, "zIndex");
 
4562
                            // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
 
4563
                            if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
 
4564
                                bRequiresBump = true;
 
4565
                            }
 
4566
                        }
 
4567
 
 
4568
                        if (bRequiresBump) {
 
4569
                            oOverlay.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
 
4570
                        }
 
4571
                    }
 
4572
                    aOverlays.sort(this.compareZIndexDesc);
 
4573
                }
 
4574
            }
 
4575
        },
 
4576
 
 
4577
        /**
 
4578
        * Attempts to locate an Overlay by instance or ID.
 
4579
        * @method find
 
4580
        * @param {Overlay} overlay  An Overlay to locate within the manager
 
4581
        * @param {String} overlay  An Overlay id to locate within the manager
 
4582
        * @return {Overlay} The requested Overlay, if found, or null if it 
 
4583
        * cannot be located.
 
4584
        */
 
4585
        find: function (overlay) {
 
4586
 
 
4587
            var isInstance = overlay instanceof Overlay,
 
4588
                overlays = this.overlays,
 
4589
                n = overlays.length,
 
4590
                found = null,
 
4591
                o,
 
4592
                i;
 
4593
 
 
4594
            if (isInstance || typeof overlay == "string") {
 
4595
                for (i = n-1; i >= 0; i--) {
 
4596
                    o = overlays[i];
 
4597
                    if ((isInstance && (o === overlay)) || (o.id == overlay)) {
 
4598
                        found = o;
 
4599
                        break;
 
4600
                    }
 
4601
                }
 
4602
            }
 
4603
 
 
4604
            return found;
 
4605
        },
 
4606
 
 
4607
        /**
 
4608
        * Used for sorting the manager's Overlays by z-index.
 
4609
        * @method compareZIndexDesc
 
4610
        * @private
 
4611
        * @return {Number} 0, 1, or -1, depending on where the Overlay should 
 
4612
        * fall in the stacking order.
 
4613
        */
 
4614
        compareZIndexDesc: function (o1, o2) {
 
4615
 
 
4616
            var zIndex1 = (o1.cfg) ? o1.cfg.getProperty("zIndex") : null, // Sort invalid (destroyed)
 
4617
                zIndex2 = (o2.cfg) ? o2.cfg.getProperty("zIndex") : null; // objects at bottom.
 
4618
 
 
4619
            if (zIndex1 === null && zIndex2 === null) {
 
4620
                return 0;
 
4621
            } else if (zIndex1 === null){
 
4622
                return 1;
 
4623
            } else if (zIndex2 === null) {
 
4624
                return -1;
 
4625
            } else if (zIndex1 > zIndex2) {
 
4626
                return -1;
 
4627
            } else if (zIndex1 < zIndex2) {
 
4628
                return 1;
 
4629
            } else {
 
4630
                return 0;
 
4631
            }
 
4632
        },
 
4633
 
 
4634
        /**
 
4635
        * Shows all Overlays in the manager.
 
4636
        * @method showAll
 
4637
        */
 
4638
        showAll: function () {
 
4639
            var overlays = this.overlays,
 
4640
                n = overlays.length,
 
4641
                i;
 
4642
 
 
4643
            for (i = n - 1; i >= 0; i--) {
 
4644
                overlays[i].show();
 
4645
            }
 
4646
        },
 
4647
 
 
4648
        /**
 
4649
        * Hides all Overlays in the manager.
 
4650
        * @method hideAll
 
4651
        */
 
4652
        hideAll: function () {
 
4653
            var overlays = this.overlays,
 
4654
                n = overlays.length,
 
4655
                i;
 
4656
 
 
4657
            for (i = n - 1; i >= 0; i--) {
 
4658
                overlays[i].hide();
 
4659
            }
 
4660
        },
 
4661
 
 
4662
        /**
 
4663
        * Returns a string representation of the object.
 
4664
        * @method toString
 
4665
        * @return {String} The string representation of the OverlayManager
 
4666
        */
 
4667
        toString: function () {
 
4668
            return "OverlayManager";
 
4669
        }
 
4670
    };
 
4671
}());
 
4672
 
 
4673
(function () {
 
4674
 
 
4675
    /**
 
4676
    * ContainerEffect encapsulates animation transitions that are executed when 
 
4677
    * an Overlay is shown or hidden.
 
4678
    * @namespace YAHOO.widget
 
4679
    * @class ContainerEffect
 
4680
    * @constructor
 
4681
    * @param {YAHOO.widget.Overlay} overlay The Overlay that the animation 
 
4682
    * should be associated with
 
4683
    * @param {Object} attrIn The object literal representing the animation 
 
4684
    * arguments to be used for the animate-in transition. The arguments for 
 
4685
    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
 
4686
    * duration(Number), and method(i.e. Easing.easeIn).
 
4687
    * @param {Object} attrOut The object literal representing the animation 
 
4688
    * arguments to be used for the animate-out transition. The arguments for  
 
4689
    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
 
4690
    * duration(Number), and method(i.e. Easing.easeIn).
 
4691
    * @param {HTMLElement} targetElement Optional. The target element that  
 
4692
    * should be animated during the transition. Defaults to overlay.element.
 
4693
    * @param {class} Optional. The animation class to instantiate. Defaults to 
 
4694
    * YAHOO.util.Anim. Other options include YAHOO.util.Motion.
 
4695
    */
 
4696
    YAHOO.widget.ContainerEffect = function (overlay, attrIn, attrOut, targetElement, animClass) {
 
4697
 
 
4698
        if (!animClass) {
 
4699
            animClass = YAHOO.util.Anim;
 
4700
        }
 
4701
 
 
4702
        /**
 
4703
        * The overlay to animate
 
4704
        * @property overlay
 
4705
        * @type YAHOO.widget.Overlay
 
4706
        */
 
4707
        this.overlay = overlay;
 
4708
    
 
4709
        /**
 
4710
        * The animation attributes to use when transitioning into view
 
4711
        * @property attrIn
 
4712
        * @type Object
 
4713
        */
 
4714
        this.attrIn = attrIn;
 
4715
    
 
4716
        /**
 
4717
        * The animation attributes to use when transitioning out of view
 
4718
        * @property attrOut
 
4719
        * @type Object
 
4720
        */
 
4721
        this.attrOut = attrOut;
 
4722
    
 
4723
        /**
 
4724
        * The target element to be animated
 
4725
        * @property targetElement
 
4726
        * @type HTMLElement
 
4727
        */
 
4728
        this.targetElement = targetElement || overlay.element;
 
4729
    
 
4730
        /**
 
4731
        * The animation class to use for animating the overlay
 
4732
        * @property animClass
 
4733
        * @type class
 
4734
        */
 
4735
        this.animClass = animClass;
 
4736
    
 
4737
    };
 
4738
 
 
4739
 
 
4740
    var Dom = YAHOO.util.Dom,
 
4741
        CustomEvent = YAHOO.util.CustomEvent,
 
4742
        ContainerEffect = YAHOO.widget.ContainerEffect;
 
4743
 
 
4744
 
 
4745
    /**
 
4746
    * A pre-configured ContainerEffect instance that can be used for fading 
 
4747
    * an overlay in and out.
 
4748
    * @method FADE
 
4749
    * @static
 
4750
    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
 
4751
    * @param {Number} dur The duration of the animation
 
4752
    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
 
4753
    */
 
4754
    ContainerEffect.FADE = function (overlay, dur) {
 
4755
 
 
4756
        var Easing = YAHOO.util.Easing,
 
4757
            fin = {
 
4758
                attributes: {opacity:{from:0, to:1}},
 
4759
                duration: dur,
 
4760
                method: Easing.easeIn
 
4761
            },
 
4762
            fout = {
 
4763
                attributes: {opacity:{to:0}},
 
4764
                duration: dur,
 
4765
                method: Easing.easeOut
 
4766
            },
 
4767
            fade = new ContainerEffect(overlay, fin, fout, overlay.element);
 
4768
 
 
4769
        fade.handleUnderlayStart = function() {
 
4770
            var underlay = this.overlay.underlay;
 
4771
            if (underlay && YAHOO.env.ua.ie) {
 
4772
                var hasFilters = (underlay.filters && underlay.filters.length > 0);
 
4773
                if(hasFilters) {
 
4774
                    Dom.addClass(overlay.element, "yui-effect-fade");
 
4775
                }
 
4776
            }
 
4777
        };
 
4778
 
 
4779
        fade.handleUnderlayComplete = function() {
 
4780
            var underlay = this.overlay.underlay;
 
4781
            if (underlay && YAHOO.env.ua.ie) {
 
4782
                Dom.removeClass(overlay.element, "yui-effect-fade");
 
4783
            }
 
4784
        };
 
4785
 
 
4786
        fade.handleStartAnimateIn = function (type, args, obj) {
 
4787
            Dom.addClass(obj.overlay.element, "hide-select");
 
4788
 
 
4789
            if (!obj.overlay.underlay) {
 
4790
                obj.overlay.cfg.refireEvent("underlay");
 
4791
            }
 
4792
 
 
4793
            obj.handleUnderlayStart();
 
4794
 
 
4795
            Dom.setStyle(obj.overlay.element, "visibility", "visible");
 
4796
            Dom.setStyle(obj.overlay.element, "opacity", 0);
 
4797
        };
 
4798
 
 
4799
        fade.handleCompleteAnimateIn = function (type,args,obj) {
 
4800
            Dom.removeClass(obj.overlay.element, "hide-select");
 
4801
 
 
4802
            if (obj.overlay.element.style.filter) {
 
4803
                obj.overlay.element.style.filter = null;
 
4804
            }
 
4805
 
 
4806
            obj.handleUnderlayComplete();
 
4807
 
 
4808
            obj.overlay.cfg.refireEvent("iframe");
 
4809
            obj.animateInCompleteEvent.fire();
 
4810
        };
 
4811
 
 
4812
        fade.handleStartAnimateOut = function (type, args, obj) {
 
4813
            Dom.addClass(obj.overlay.element, "hide-select");
 
4814
            obj.handleUnderlayStart();
 
4815
        };
 
4816
 
 
4817
        fade.handleCompleteAnimateOut =  function (type, args, obj) {
 
4818
            Dom.removeClass(obj.overlay.element, "hide-select");
 
4819
            if (obj.overlay.element.style.filter) {
 
4820
                obj.overlay.element.style.filter = null;
 
4821
            }
 
4822
            Dom.setStyle(obj.overlay.element, "visibility", "hidden");
 
4823
            Dom.setStyle(obj.overlay.element, "opacity", 1);
 
4824
 
 
4825
            obj.handleUnderlayComplete();
 
4826
 
 
4827
            obj.overlay.cfg.refireEvent("iframe");
 
4828
            obj.animateOutCompleteEvent.fire();
 
4829
        };
 
4830
 
 
4831
        fade.init();
 
4832
        return fade;
 
4833
    };
 
4834
    
 
4835
    
 
4836
    /**
 
4837
    * A pre-configured ContainerEffect instance that can be used for sliding an 
 
4838
    * overlay in and out.
 
4839
    * @method SLIDE
 
4840
    * @static
 
4841
    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
 
4842
    * @param {Number} dur The duration of the animation
 
4843
    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
 
4844
    */
 
4845
    ContainerEffect.SLIDE = function (overlay, dur) {
 
4846
        var Easing = YAHOO.util.Easing,
 
4847
 
 
4848
            x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
 
4849
            y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
 
4850
            clientWidth = Dom.getClientWidth(),
 
4851
            offsetWidth = overlay.element.offsetWidth,
 
4852
 
 
4853
            sin =  { 
 
4854
                attributes: { points: { to: [x, y] } },
 
4855
                duration: dur,
 
4856
                method: Easing.easeIn 
 
4857
            },
 
4858
 
 
4859
            sout = {
 
4860
                attributes: { points: { to: [(clientWidth + 25), y] } },
 
4861
                duration: dur,
 
4862
                method: Easing.easeOut 
 
4863
            },
 
4864
 
 
4865
            slide = new ContainerEffect(overlay, sin, sout, overlay.element, YAHOO.util.Motion);
 
4866
 
 
4867
        slide.handleStartAnimateIn = function (type,args,obj) {
 
4868
            obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
 
4869
            obj.overlay.element.style.top  = y + "px";
 
4870
        };
 
4871
 
 
4872
        slide.handleTweenAnimateIn = function (type, args, obj) {
 
4873
        
 
4874
            var pos = Dom.getXY(obj.overlay.element),
 
4875
                currentX = pos[0],
 
4876
                currentY = pos[1];
 
4877
        
 
4878
            if (Dom.getStyle(obj.overlay.element, "visibility") == 
 
4879
                "hidden" && currentX < x) {
 
4880
 
 
4881
                Dom.setStyle(obj.overlay.element, "visibility", "visible");
 
4882
 
 
4883
            }
 
4884
        
 
4885
            obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
 
4886
            obj.overlay.cfg.refireEvent("iframe");
 
4887
        };
 
4888
        
 
4889
        slide.handleCompleteAnimateIn = function (type, args, obj) {
 
4890
            obj.overlay.cfg.setProperty("xy", [x, y], true);
 
4891
            obj.startX = x;
 
4892
            obj.startY = y;
 
4893
            obj.overlay.cfg.refireEvent("iframe");
 
4894
            obj.animateInCompleteEvent.fire();
 
4895
        };
 
4896
        
 
4897
        slide.handleStartAnimateOut = function (type, args, obj) {
 
4898
    
 
4899
            var vw = Dom.getViewportWidth(),
 
4900
                pos = Dom.getXY(obj.overlay.element),
 
4901
                yso = pos[1];
 
4902
    
 
4903
            obj.animOut.attributes.points.to = [(vw + 25), yso];
 
4904
        };
 
4905
        
 
4906
        slide.handleTweenAnimateOut = function (type, args, obj) {
 
4907
    
 
4908
            var pos = Dom.getXY(obj.overlay.element),
 
4909
                xto = pos[0],
 
4910
                yto = pos[1];
 
4911
        
 
4912
            obj.overlay.cfg.setProperty("xy", [xto, yto], true);
 
4913
            obj.overlay.cfg.refireEvent("iframe");
 
4914
        };
 
4915
        
 
4916
        slide.handleCompleteAnimateOut = function (type, args, obj) {
 
4917
            Dom.setStyle(obj.overlay.element, "visibility", "hidden");
 
4918
        
 
4919
            obj.overlay.cfg.setProperty("xy", [x, y]);
 
4920
            obj.animateOutCompleteEvent.fire();
 
4921
        };
 
4922
 
 
4923
        slide.init();
 
4924
        return slide;
 
4925
    };
 
4926
 
 
4927
    ContainerEffect.prototype = {
 
4928
 
 
4929
        /**
 
4930
        * Initializes the animation classes and events.
 
4931
        * @method init
 
4932
        */
 
4933
        init: function () {
 
4934
 
 
4935
            this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
 
4936
            this.beforeAnimateInEvent.signature = CustomEvent.LIST;
 
4937
            
 
4938
            this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
 
4939
            this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
 
4940
        
 
4941
            this.animateInCompleteEvent = this.createEvent("animateInComplete");
 
4942
            this.animateInCompleteEvent.signature = CustomEvent.LIST;
 
4943
        
 
4944
            this.animateOutCompleteEvent = 
 
4945
                this.createEvent("animateOutComplete");
 
4946
            this.animateOutCompleteEvent.signature = CustomEvent.LIST;
 
4947
        
 
4948
            this.animIn = new this.animClass(this.targetElement, 
 
4949
                this.attrIn.attributes, this.attrIn.duration, 
 
4950
                this.attrIn.method);
 
4951
 
 
4952
            this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
 
4953
            this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
 
4954
 
 
4955
            this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn, 
 
4956
                this);
 
4957
        
 
4958
            this.animOut = new this.animClass(this.targetElement, 
 
4959
                this.attrOut.attributes, this.attrOut.duration, 
 
4960
                this.attrOut.method);
 
4961
 
 
4962
            this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
 
4963
            this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
 
4964
            this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut, 
 
4965
                this);
 
4966
 
 
4967
        },
 
4968
        
 
4969
        /**
 
4970
        * Triggers the in-animation.
 
4971
        * @method animateIn
 
4972
        */
 
4973
        animateIn: function () {
 
4974
            this.beforeAnimateInEvent.fire();
 
4975
            this.animIn.animate();
 
4976
        },
 
4977
 
 
4978
        /**
 
4979
        * Triggers the out-animation.
 
4980
        * @method animateOut
 
4981
        */
 
4982
        animateOut: function () {
 
4983
            this.beforeAnimateOutEvent.fire();
 
4984
            this.animOut.animate();
 
4985
        },
 
4986
 
 
4987
        /**
 
4988
        * The default onStart handler for the in-animation.
 
4989
        * @method handleStartAnimateIn
 
4990
        * @param {String} type The CustomEvent type
 
4991
        * @param {Object[]} args The CustomEvent arguments
 
4992
        * @param {Object} obj The scope object
 
4993
        */
 
4994
        handleStartAnimateIn: function (type, args, obj) { },
 
4995
 
 
4996
        /**
 
4997
        * The default onTween handler for the in-animation.
 
4998
        * @method handleTweenAnimateIn
 
4999
        * @param {String} type The CustomEvent type
 
5000
        * @param {Object[]} args The CustomEvent arguments
 
5001
        * @param {Object} obj The scope object
 
5002
        */
 
5003
        handleTweenAnimateIn: function (type, args, obj) { },
 
5004
 
 
5005
        /**
 
5006
        * The default onComplete handler for the in-animation.
 
5007
        * @method handleCompleteAnimateIn
 
5008
        * @param {String} type The CustomEvent type
 
5009
        * @param {Object[]} args The CustomEvent arguments
 
5010
        * @param {Object} obj The scope object
 
5011
        */
 
5012
        handleCompleteAnimateIn: function (type, args, obj) { },
 
5013
 
 
5014
        /**
 
5015
        * The default onStart handler for the out-animation.
 
5016
        * @method handleStartAnimateOut
 
5017
        * @param {String} type The CustomEvent type
 
5018
        * @param {Object[]} args The CustomEvent arguments
 
5019
        * @param {Object} obj The scope object
 
5020
        */
 
5021
        handleStartAnimateOut: function (type, args, obj) { },
 
5022
 
 
5023
        /**
 
5024
        * The default onTween handler for the out-animation.
 
5025
        * @method handleTweenAnimateOut
 
5026
        * @param {String} type The CustomEvent type
 
5027
        * @param {Object[]} args The CustomEvent arguments
 
5028
        * @param {Object} obj The scope object
 
5029
        */
 
5030
        handleTweenAnimateOut: function (type, args, obj) { },
 
5031
 
 
5032
        /**
 
5033
        * The default onComplete handler for the out-animation.
 
5034
        * @method handleCompleteAnimateOut
 
5035
        * @param {String} type The CustomEvent type
 
5036
        * @param {Object[]} args The CustomEvent arguments
 
5037
        * @param {Object} obj The scope object
 
5038
        */
 
5039
        handleCompleteAnimateOut: function (type, args, obj) { },
 
5040
        
 
5041
        /**
 
5042
        * Returns a string representation of the object.
 
5043
        * @method toString
 
5044
        * @return {String} The string representation of the ContainerEffect
 
5045
        */
 
5046
        toString: function () {
 
5047
            var output = "ContainerEffect";
 
5048
            if (this.overlay) {
 
5049
                output += " [" + this.overlay.toString() + "]";
 
5050
            }
 
5051
            return output;
 
5052
        }
 
5053
    };
 
5054
 
 
5055
    YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
 
5056
 
 
5057
})();
 
5058
 
 
5059
YAHOO.register("containercore", YAHOO.widget.Module, {version: "2.6.0", build: "1321"});