~ubuntu-branches/ubuntu/natty/otrs2/natty-updates

« back to all changes in this revision

Viewing changes to var/httpd/htdocs/yui/2.7.0/build/container/container_core.js

  • Committer: Package Import Robot
  • Author(s): Patrick Matthäi
  • Date: 2010-08-09 19:43:44 UTC
  • mfrom: (1.1.12)
  • Revision ID: package-import@ubuntu.com-20100809194344-absef1ut5mfj3qhv
Tags: 2.4.7+dfsg1-1
* Strip out yui from the source in the dfsg version.
  Closes: #591196
* Depend on libjs-yui and link to this package, instead of using the embedded
  yui version. This changes make the flash ticket statistics unuseable!
  Closes: #592146

Show diffs side-by-side

added added

removed removed

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