~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-debug.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
 
        if (!owner) {  YAHOO.log("No owner specified for Config object", "error", "Config"); }
27
 
 
28
 
    };
29
 
 
30
 
 
31
 
    var Lang = YAHOO.lang,
32
 
        CustomEvent = YAHOO.util.CustomEvent,
33
 
        Config = YAHOO.util.Config;
34
 
 
35
 
 
36
 
    /**
37
 
     * Constant representing the CustomEvent type for the config changed event.
38
 
     * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
39
 
     * @private
40
 
     * @static
41
 
     * @final
42
 
     */
43
 
    Config.CONFIG_CHANGED_EVENT = "configChanged";
44
 
    
45
 
    /**
46
 
     * Constant representing the boolean type string
47
 
     * @property YAHOO.util.Config.BOOLEAN_TYPE
48
 
     * @private
49
 
     * @static
50
 
     * @final
51
 
     */
52
 
    Config.BOOLEAN_TYPE = "boolean";
53
 
    
54
 
    Config.prototype = {
55
 
     
56
 
        /**
57
 
        * Object reference to the owner of this Config Object
58
 
        * @property owner
59
 
        * @type Object
60
 
        */
61
 
        owner: null,
62
 
        
63
 
        /**
64
 
        * Boolean flag that specifies whether a queue is currently 
65
 
        * being executed
66
 
        * @property queueInProgress
67
 
        * @type Boolean
68
 
        */
69
 
        queueInProgress: false,
70
 
        
71
 
        /**
72
 
        * Maintains the local collection of configuration property objects and 
73
 
        * their specified values
74
 
        * @property config
75
 
        * @private
76
 
        * @type Object
77
 
        */ 
78
 
        config: null,
79
 
        
80
 
        /**
81
 
        * Maintains the local collection of configuration property objects as 
82
 
        * they were initially applied.
83
 
        * This object is used when resetting a property.
84
 
        * @property initialConfig
85
 
        * @private
86
 
        * @type Object
87
 
        */ 
88
 
        initialConfig: null,
89
 
        
90
 
        /**
91
 
        * Maintains the local, normalized CustomEvent queue
92
 
        * @property eventQueue
93
 
        * @private
94
 
        * @type Object
95
 
        */ 
96
 
        eventQueue: null,
97
 
        
98
 
        /**
99
 
        * Custom Event, notifying subscribers when Config properties are set 
100
 
        * (setProperty is called without the silent flag
101
 
        * @event configChangedEvent
102
 
        */
103
 
        configChangedEvent: null,
104
 
    
105
 
        /**
106
 
        * Initializes the configuration Object and all of its local members.
107
 
        * @method init
108
 
        * @param {Object} owner The owner Object to which this Config 
109
 
        * Object belongs
110
 
        */
111
 
        init: function (owner) {
112
 
    
113
 
            this.owner = owner;
114
 
    
115
 
            this.configChangedEvent = 
116
 
                this.createEvent(Config.CONFIG_CHANGED_EVENT);
117
 
    
118
 
            this.configChangedEvent.signature = CustomEvent.LIST;
119
 
            this.queueInProgress = false;
120
 
            this.config = {};
121
 
            this.initialConfig = {};
122
 
            this.eventQueue = [];
123
 
        
124
 
        },
125
 
        
126
 
        /**
127
 
        * Validates that the value passed in is a Boolean.
128
 
        * @method checkBoolean
129
 
        * @param {Object} val The value to validate
130
 
        * @return {Boolean} true, if the value is valid
131
 
        */ 
132
 
        checkBoolean: function (val) {
133
 
            return (typeof val == Config.BOOLEAN_TYPE);
134
 
        },
135
 
        
136
 
        /**
137
 
        * Validates that the value passed in is a number.
138
 
        * @method checkNumber
139
 
        * @param {Object} val The value to validate
140
 
        * @return {Boolean} true, if the value is valid
141
 
        */
142
 
        checkNumber: function (val) {
143
 
            return (!isNaN(val));
144
 
        },
145
 
        
146
 
        /**
147
 
        * Fires a configuration property event using the specified value. 
148
 
        * @method fireEvent
149
 
        * @private
150
 
        * @param {String} key The configuration property's name
151
 
        * @param {value} Object The value of the correct type for the property
152
 
        */ 
153
 
        fireEvent: function ( key, value ) {
154
 
            YAHOO.log("Firing Config event: " + key + "=" + value, "info", "Config");
155
 
            var property = this.config[key];
156
 
        
157
 
            if (property && property.event) {
158
 
                property.event.fire(value);
159
 
            } 
160
 
        },
161
 
        
162
 
        /**
163
 
        * Adds a property to the Config Object's private config hash.
164
 
        * @method addProperty
165
 
        * @param {String} key The configuration property's name
166
 
        * @param {Object} propertyObject The Object containing all of this 
167
 
        * property's arguments
168
 
        */
169
 
        addProperty: function ( key, propertyObject ) {
170
 
            key = key.toLowerCase();
171
 
            YAHOO.log("Added property: " + key, "info", "Config");
172
 
        
173
 
            this.config[key] = propertyObject;
174
 
        
175
 
            propertyObject.event = this.createEvent(key, { scope: this.owner });
176
 
            propertyObject.event.signature = CustomEvent.LIST;
177
 
            
178
 
            
179
 
            propertyObject.key = key;
180
 
        
181
 
            if (propertyObject.handler) {
182
 
                propertyObject.event.subscribe(propertyObject.handler, 
183
 
                    this.owner);
184
 
            }
185
 
        
186
 
            this.setProperty(key, propertyObject.value, true);
187
 
            
188
 
            if (! propertyObject.suppressEvent) {
189
 
                this.queueProperty(key, propertyObject.value);
190
 
            }
191
 
            
192
 
        },
193
 
        
194
 
        /**
195
 
        * Returns a key-value configuration map of the values currently set in  
196
 
        * the Config Object.
197
 
        * @method getConfig
198
 
        * @return {Object} The current config, represented in a key-value map
199
 
        */
200
 
        getConfig: function () {
201
 
        
202
 
            var cfg = {},
203
 
                currCfg = this.config,
204
 
                prop,
205
 
                property;
206
 
                
207
 
            for (prop in currCfg) {
208
 
                if (Lang.hasOwnProperty(currCfg, prop)) {
209
 
                    property = currCfg[prop];
210
 
                    if (property && property.event) {
211
 
                        cfg[prop] = property.value;
212
 
                    }
213
 
                }
214
 
            }
215
 
 
216
 
            return cfg;
217
 
        },
218
 
        
219
 
        /**
220
 
        * Returns the value of specified property.
221
 
        * @method getProperty
222
 
        * @param {String} key The name of the property
223
 
        * @return {Object}  The value of the specified property
224
 
        */
225
 
        getProperty: function (key) {
226
 
            var property = this.config[key.toLowerCase()];
227
 
            if (property && property.event) {
228
 
                return property.value;
229
 
            } else {
230
 
                return undefined;
231
 
            }
232
 
        },
233
 
        
234
 
        /**
235
 
        * Resets the specified property's value to its initial value.
236
 
        * @method resetProperty
237
 
        * @param {String} key The name of the property
238
 
        * @return {Boolean} True is the property was reset, false if not
239
 
        */
240
 
        resetProperty: function (key) {
241
 
    
242
 
            key = key.toLowerCase();
243
 
        
244
 
            var property = this.config[key];
245
 
    
246
 
            if (property && property.event) {
247
 
    
248
 
                if (this.initialConfig[key] && 
249
 
                    !Lang.isUndefined(this.initialConfig[key])) {
250
 
    
251
 
                    this.setProperty(key, this.initialConfig[key]);
252
 
 
253
 
                    return true;
254
 
    
255
 
                }
256
 
    
257
 
            } else {
258
 
    
259
 
                return false;
260
 
            }
261
 
    
262
 
        },
263
 
        
264
 
        /**
265
 
        * Sets the value of a property. If the silent property is passed as 
266
 
        * true, the property's event will not be fired.
267
 
        * @method setProperty
268
 
        * @param {String} key The name of the property
269
 
        * @param {String} value The value to set the property to
270
 
        * @param {Boolean} silent Whether the value should be set silently, 
271
 
        * without firing the property event.
272
 
        * @return {Boolean} True, if the set was successful, false if it failed.
273
 
        */
274
 
        setProperty: function (key, value, silent) {
275
 
        
276
 
            var property;
277
 
        
278
 
            key = key.toLowerCase();
279
 
            YAHOO.log("setProperty: " + key + "=" + value, "info", "Config");
280
 
        
281
 
            if (this.queueInProgress && ! silent) {
282
 
                // Currently running through a queue... 
283
 
                this.queueProperty(key,value);
284
 
                return true;
285
 
    
286
 
            } else {
287
 
                property = this.config[key];
288
 
                if (property && property.event) {
289
 
                    if (property.validator && !property.validator(value)) {
290
 
                        return false;
291
 
                    } else {
292
 
                        property.value = value;
293
 
                        if (! silent) {
294
 
                            this.fireEvent(key, value);
295
 
                            this.configChangedEvent.fire([key, value]);
296
 
                        }
297
 
                        return true;
298
 
                    }
299
 
                } else {
300
 
                    return false;
301
 
                }
302
 
            }
303
 
        },
304
 
        
305
 
        /**
306
 
        * Sets the value of a property and queues its event to execute. If the 
307
 
        * event is already scheduled to execute, it is
308
 
        * moved from its current position to the end of the queue.
309
 
        * @method queueProperty
310
 
        * @param {String} key The name of the property
311
 
        * @param {String} value The value to set the property to
312
 
        * @return {Boolean}  true, if the set was successful, false if 
313
 
        * it failed.
314
 
        */ 
315
 
        queueProperty: function (key, value) {
316
 
        
317
 
            key = key.toLowerCase();
318
 
            YAHOO.log("queueProperty: " + key + "=" + value, "info", "Config");
319
 
        
320
 
            var property = this.config[key],
321
 
                foundDuplicate = false,
322
 
                iLen,
323
 
                queueItem,
324
 
                queueItemKey,
325
 
                queueItemValue,
326
 
                sLen,
327
 
                supercedesCheck,
328
 
                qLen,
329
 
                queueItemCheck,
330
 
                queueItemCheckKey,
331
 
                queueItemCheckValue,
332
 
                i,
333
 
                s,
334
 
                q;
335
 
                                
336
 
            if (property && property.event) {
337
 
    
338
 
                if (!Lang.isUndefined(value) && property.validator && 
339
 
                    !property.validator(value)) { // validator
340
 
                    return false;
341
 
                } else {
342
 
        
343
 
                    if (!Lang.isUndefined(value)) {
344
 
                        property.value = value;
345
 
                    } else {
346
 
                        value = property.value;
347
 
                    }
348
 
        
349
 
                    foundDuplicate = false;
350
 
                    iLen = this.eventQueue.length;
351
 
        
352
 
                    for (i = 0; i < iLen; i++) {
353
 
                        queueItem = this.eventQueue[i];
354
 
        
355
 
                        if (queueItem) {
356
 
                            queueItemKey = queueItem[0];
357
 
                            queueItemValue = queueItem[1];
358
 
 
359
 
                            if (queueItemKey == key) {
360
 
    
361
 
                                /*
362
 
                                    found a dupe... push to end of queue, null 
363
 
                                    current item, and break
364
 
                                */
365
 
    
366
 
                                this.eventQueue[i] = null;
367
 
    
368
 
                                this.eventQueue.push(
369
 
                                    [key, (!Lang.isUndefined(value) ? 
370
 
                                    value : queueItemValue)]);
371
 
    
372
 
                                foundDuplicate = true;
373
 
                                break;
374
 
                            }
375
 
                        }
376
 
                    }
377
 
                    
378
 
                    // this is a refire, or a new property in the queue
379
 
    
380
 
                    if (! foundDuplicate && !Lang.isUndefined(value)) { 
381
 
                        this.eventQueue.push([key, value]);
382
 
                    }
383
 
                }
384
 
        
385
 
                if (property.supercedes) {
386
 
 
387
 
                    sLen = property.supercedes.length;
388
 
 
389
 
                    for (s = 0; s < sLen; s++) {
390
 
 
391
 
                        supercedesCheck = property.supercedes[s];
392
 
                        qLen = this.eventQueue.length;
393
 
 
394
 
                        for (q = 0; q < qLen; q++) {
395
 
                            queueItemCheck = this.eventQueue[q];
396
 
 
397
 
                            if (queueItemCheck) {
398
 
                                queueItemCheckKey = queueItemCheck[0];
399
 
                                queueItemCheckValue = queueItemCheck[1];
400
 
 
401
 
                                if (queueItemCheckKey == 
402
 
                                    supercedesCheck.toLowerCase() ) {
403
 
 
404
 
                                    this.eventQueue.push([queueItemCheckKey, 
405
 
                                        queueItemCheckValue]);
406
 
 
407
 
                                    this.eventQueue[q] = null;
408
 
                                    break;
409
 
 
410
 
                                }
411
 
                            }
412
 
                        }
413
 
                    }
414
 
                }
415
 
 
416
 
                YAHOO.log("Config event queue: " + this.outputEventQueue(), "info", "Config");
417
 
 
418
 
                return true;
419
 
            } else {
420
 
                return false;
421
 
            }
422
 
        },
423
 
        
424
 
        /**
425
 
        * Fires the event for a property using the property's current value.
426
 
        * @method refireEvent
427
 
        * @param {String} key The name of the property
428
 
        */
429
 
        refireEvent: function (key) {
430
 
    
431
 
            key = key.toLowerCase();
432
 
        
433
 
            var property = this.config[key];
434
 
    
435
 
            if (property && property.event && 
436
 
    
437
 
                !Lang.isUndefined(property.value)) {
438
 
    
439
 
                if (this.queueInProgress) {
440
 
    
441
 
                    this.queueProperty(key);
442
 
    
443
 
                } else {
444
 
    
445
 
                    this.fireEvent(key, property.value);
446
 
    
447
 
                }
448
 
    
449
 
            }
450
 
        },
451
 
        
452
 
        /**
453
 
        * Applies a key-value Object literal to the configuration, replacing  
454
 
        * any existing values, and queueing the property events.
455
 
        * Although the values will be set, fireQueue() must be called for their 
456
 
        * associated events to execute.
457
 
        * @method applyConfig
458
 
        * @param {Object} userConfig The configuration Object literal
459
 
        * @param {Boolean} init  When set to true, the initialConfig will 
460
 
        * be set to the userConfig passed in, so that calling a reset will 
461
 
        * reset the properties to the passed values.
462
 
        */
463
 
        applyConfig: function (userConfig, init) {
464
 
        
465
 
            var sKey,
466
 
                oConfig;
467
 
 
468
 
            if (init) {
469
 
                oConfig = {};
470
 
                for (sKey in userConfig) {
471
 
                    if (Lang.hasOwnProperty(userConfig, sKey)) {
472
 
                        oConfig[sKey.toLowerCase()] = userConfig[sKey];
473
 
                    }
474
 
                }
475
 
                this.initialConfig = oConfig;
476
 
            }
477
 
 
478
 
            for (sKey in userConfig) {
479
 
                if (Lang.hasOwnProperty(userConfig, sKey)) {
480
 
                    this.queueProperty(sKey, userConfig[sKey]);
481
 
                }
482
 
            }
483
 
        },
484
 
        
485
 
        /**
486
 
        * Refires the events for all configuration properties using their 
487
 
        * current values.
488
 
        * @method refresh
489
 
        */
490
 
        refresh: function () {
491
 
 
492
 
            var prop;
493
 
 
494
 
            for (prop in this.config) {
495
 
                if (Lang.hasOwnProperty(this.config, prop)) {
496
 
                    this.refireEvent(prop);
497
 
                }
498
 
            }
499
 
        },
500
 
        
501
 
        /**
502
 
        * Fires the normalized list of queued property change events
503
 
        * @method fireQueue
504
 
        */
505
 
        fireQueue: function () {
506
 
        
507
 
            var i, 
508
 
                queueItem,
509
 
                key,
510
 
                value,
511
 
                property;
512
 
        
513
 
            this.queueInProgress = true;
514
 
            for (i = 0;i < this.eventQueue.length; i++) {
515
 
                queueItem = this.eventQueue[i];
516
 
                if (queueItem) {
517
 
        
518
 
                    key = queueItem[0];
519
 
                    value = queueItem[1];
520
 
                    property = this.config[key];
521
 
 
522
 
                    property.value = value;
523
 
 
524
 
                    // Clear out queue entry, to avoid it being 
525
 
                    // re-added to the queue by any queueProperty/supercedes
526
 
                    // calls which are invoked during fireEvent
527
 
                    this.eventQueue[i] = null;
528
 
 
529
 
                    this.fireEvent(key,value);
530
 
                }
531
 
            }
532
 
            
533
 
            this.queueInProgress = false;
534
 
            this.eventQueue = [];
535
 
        },
536
 
        
537
 
        /**
538
 
        * Subscribes an external handler to the change event for any 
539
 
        * given property. 
540
 
        * @method subscribeToConfigEvent
541
 
        * @param {String} key The property name
542
 
        * @param {Function} handler The handler function to use subscribe to 
543
 
        * the property's event
544
 
        * @param {Object} obj The Object to use for scoping the event handler 
545
 
        * (see CustomEvent documentation)
546
 
        * @param {Boolean} override Optional. If true, will override "this"  
547
 
        * within the handler to map to the scope Object passed into the method.
548
 
        * @return {Boolean} True, if the subscription was successful, 
549
 
        * otherwise false.
550
 
        */ 
551
 
        subscribeToConfigEvent: function (key, handler, obj, override) {
552
 
    
553
 
            var property = this.config[key.toLowerCase()];
554
 
    
555
 
            if (property && property.event) {
556
 
                if (!Config.alreadySubscribed(property.event, handler, obj)) {
557
 
                    property.event.subscribe(handler, obj, override);
558
 
                }
559
 
                return true;
560
 
            } else {
561
 
                return false;
562
 
            }
563
 
    
564
 
        },
565
 
        
566
 
        /**
567
 
        * Unsubscribes an external handler from the change event for any 
568
 
        * given property. 
569
 
        * @method unsubscribeFromConfigEvent
570
 
        * @param {String} key The property name
571
 
        * @param {Function} handler The handler function to use subscribe to 
572
 
        * the property's event
573
 
        * @param {Object} obj The Object to use for scoping the event 
574
 
        * handler (see CustomEvent documentation)
575
 
        * @return {Boolean} True, if the unsubscription was successful, 
576
 
        * otherwise false.
577
 
        */
578
 
        unsubscribeFromConfigEvent: function (key, handler, obj) {
579
 
            var property = this.config[key.toLowerCase()];
580
 
            if (property && property.event) {
581
 
                return property.event.unsubscribe(handler, obj);
582
 
            } else {
583
 
                return false;
584
 
            }
585
 
        },
586
 
        
587
 
        /**
588
 
        * Returns a string representation of the Config object
589
 
        * @method toString
590
 
        * @return {String} The Config object in string format.
591
 
        */
592
 
        toString: function () {
593
 
            var output = "Config";
594
 
            if (this.owner) {
595
 
                output += " [" + this.owner.toString() + "]";
596
 
            }
597
 
            return output;
598
 
        },
599
 
        
600
 
        /**
601
 
        * Returns a string representation of the Config object's current 
602
 
        * CustomEvent queue
603
 
        * @method outputEventQueue
604
 
        * @return {String} The string list of CustomEvents currently queued 
605
 
        * for execution
606
 
        */
607
 
        outputEventQueue: function () {
608
 
 
609
 
            var output = "",
610
 
                queueItem,
611
 
                q,
612
 
                nQueue = this.eventQueue.length;
613
 
              
614
 
            for (q = 0; q < nQueue; q++) {
615
 
                queueItem = this.eventQueue[q];
616
 
                if (queueItem) {
617
 
                    output += queueItem[0] + "=" + queueItem[1] + ", ";
618
 
                }
619
 
            }
620
 
            return output;
621
 
        },
622
 
 
623
 
        /**
624
 
        * Sets all properties to null, unsubscribes all listeners from each 
625
 
        * property's change event and all listeners from the configChangedEvent.
626
 
        * @method destroy
627
 
        */
628
 
        destroy: function () {
629
 
 
630
 
            var oConfig = this.config,
631
 
                sProperty,
632
 
                oProperty;
633
 
 
634
 
 
635
 
            for (sProperty in oConfig) {
636
 
            
637
 
                if (Lang.hasOwnProperty(oConfig, sProperty)) {
638
 
 
639
 
                    oProperty = oConfig[sProperty];
640
 
 
641
 
                    oProperty.event.unsubscribeAll();
642
 
                    oProperty.event = null;
643
 
 
644
 
                }
645
 
            
646
 
            }
647
 
            
648
 
            this.configChangedEvent.unsubscribeAll();
649
 
            
650
 
            this.configChangedEvent = null;
651
 
            this.owner = null;
652
 
            this.config = null;
653
 
            this.initialConfig = null;
654
 
            this.eventQueue = null;
655
 
        
656
 
        }
657
 
 
658
 
    };
659
 
    
660
 
    
661
 
    
662
 
    /**
663
 
    * Checks to determine if a particular function/Object pair are already 
664
 
    * subscribed to the specified CustomEvent
665
 
    * @method YAHOO.util.Config.alreadySubscribed
666
 
    * @static
667
 
    * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check 
668
 
    * the subscriptions
669
 
    * @param {Function} fn The function to look for in the subscribers list
670
 
    * @param {Object} obj The execution scope Object for the subscription
671
 
    * @return {Boolean} true, if the function/Object pair is already subscribed 
672
 
    * to the CustomEvent passed in
673
 
    */
674
 
    Config.alreadySubscribed = function (evt, fn, obj) {
675
 
    
676
 
        var nSubscribers = evt.subscribers.length,
677
 
            subsc,
678
 
            i;
679
 
 
680
 
        if (nSubscribers > 0) {
681
 
            i = nSubscribers - 1;
682
 
            do {
683
 
                subsc = evt.subscribers[i];
684
 
                if (subsc && subsc.obj == obj && subsc.fn == fn) {
685
 
                    return true;
686
 
                }
687
 
            }
688
 
            while (i--);
689
 
        }
690
 
 
691
 
        return false;
692
 
 
693
 
    };
694
 
 
695
 
    YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
696
 
 
697
 
}());
698
 
 
699
 
(function () {
700
 
 
701
 
    /**
702
 
    * The Container family of components is designed to enable developers to 
703
 
    * create different kinds of content-containing modules on the web. Module 
704
 
    * and Overlay are the most basic containers, and they can be used directly 
705
 
    * or extended to build custom containers. Also part of the Container family 
706
 
    * are four UI controls that extend Module and Overlay: Tooltip, Panel, 
707
 
    * Dialog, and SimpleDialog.
708
 
    * @module container
709
 
    * @title Container
710
 
    * @requires yahoo, dom, event 
711
 
    * @optional dragdrop, animation, button
712
 
    */
713
 
    
714
 
    /**
715
 
    * Module is a JavaScript representation of the Standard Module Format. 
716
 
    * Standard Module Format is a simple standard for markup containers where 
717
 
    * child nodes representing the header, body, and footer of the content are 
718
 
    * denoted using the CSS classes "hd", "bd", and "ft" respectively. 
719
 
    * Module is the base class for all other classes in the YUI 
720
 
    * Container package.
721
 
    * @namespace YAHOO.widget
722
 
    * @class Module
723
 
    * @constructor
724
 
    * @param {String} el The element ID representing the Module <em>OR</em>
725
 
    * @param {HTMLElement} el The element representing the Module
726
 
    * @param {Object} userConfig The configuration Object literal containing 
727
 
    * the configuration that should be set for this module. See configuration 
728
 
    * documentation for more details.
729
 
    */
730
 
    YAHOO.widget.Module = function (el, userConfig) {
731
 
        if (el) {
732
 
            this.init(el, userConfig);
733
 
        } else {
734
 
            YAHOO.log("No element or element ID specified" + 
735
 
                " for Module instantiation", "error");
736
 
        }
737
 
    };
738
 
 
739
 
    var Dom = YAHOO.util.Dom,
740
 
        Config = YAHOO.util.Config,
741
 
        Event = YAHOO.util.Event,
742
 
        CustomEvent = YAHOO.util.CustomEvent,
743
 
        Module = YAHOO.widget.Module,
744
 
        UA = YAHOO.env.ua,
745
 
 
746
 
        m_oModuleTemplate,
747
 
        m_oHeaderTemplate,
748
 
        m_oBodyTemplate,
749
 
        m_oFooterTemplate,
750
 
 
751
 
        /**
752
 
        * Constant representing the name of the Module's events
753
 
        * @property EVENT_TYPES
754
 
        * @private
755
 
        * @final
756
 
        * @type Object
757
 
        */
758
 
        EVENT_TYPES = {
759
 
            "BEFORE_INIT": "beforeInit",
760
 
            "INIT": "init",
761
 
            "APPEND": "append",
762
 
            "BEFORE_RENDER": "beforeRender",
763
 
            "RENDER": "render",
764
 
            "CHANGE_HEADER": "changeHeader",
765
 
            "CHANGE_BODY": "changeBody",
766
 
            "CHANGE_FOOTER": "changeFooter",
767
 
            "CHANGE_CONTENT": "changeContent",
768
 
            "DESTORY": "destroy",
769
 
            "BEFORE_SHOW": "beforeShow",
770
 
            "SHOW": "show",
771
 
            "BEFORE_HIDE": "beforeHide",
772
 
            "HIDE": "hide"
773
 
        },
774
 
            
775
 
        /**
776
 
        * Constant representing the Module's configuration properties
777
 
        * @property DEFAULT_CONFIG
778
 
        * @private
779
 
        * @final
780
 
        * @type Object
781
 
        */
782
 
        DEFAULT_CONFIG = {
783
 
        
784
 
            "VISIBLE": { 
785
 
                key: "visible", 
786
 
                value: true, 
787
 
                validator: YAHOO.lang.isBoolean 
788
 
            },
789
 
 
790
 
            "EFFECT": {
791
 
                key: "effect",
792
 
                suppressEvent: true,
793
 
                supercedes: ["visible"]
794
 
            },
795
 
 
796
 
            "MONITOR_RESIZE": {
797
 
                key: "monitorresize",
798
 
                value: true
799
 
            },
800
 
 
801
 
            "APPEND_TO_DOCUMENT_BODY": {
802
 
                key: "appendtodocumentbody",
803
 
                value: false
804
 
            }
805
 
        };
806
 
 
807
 
    /**
808
 
    * Constant representing the prefix path to use for non-secure images
809
 
    * @property YAHOO.widget.Module.IMG_ROOT
810
 
    * @static
811
 
    * @final
812
 
    * @type String
813
 
    */
814
 
    Module.IMG_ROOT = null;
815
 
    
816
 
    /**
817
 
    * Constant representing the prefix path to use for securely served images
818
 
    * @property YAHOO.widget.Module.IMG_ROOT_SSL
819
 
    * @static
820
 
    * @final
821
 
    * @type String
822
 
    */
823
 
    Module.IMG_ROOT_SSL = null;
824
 
    
825
 
    /**
826
 
    * Constant for the default CSS class name that represents a Module
827
 
    * @property YAHOO.widget.Module.CSS_MODULE
828
 
    * @static
829
 
    * @final
830
 
    * @type String
831
 
    */
832
 
    Module.CSS_MODULE = "yui-module";
833
 
    
834
 
    /**
835
 
    * Constant representing the module header
836
 
    * @property YAHOO.widget.Module.CSS_HEADER
837
 
    * @static
838
 
    * @final
839
 
    * @type String
840
 
    */
841
 
    Module.CSS_HEADER = "hd";
842
 
 
843
 
    /**
844
 
    * Constant representing the module body
845
 
    * @property YAHOO.widget.Module.CSS_BODY
846
 
    * @static
847
 
    * @final
848
 
    * @type String
849
 
    */
850
 
    Module.CSS_BODY = "bd";
851
 
    
852
 
    /**
853
 
    * Constant representing the module footer
854
 
    * @property YAHOO.widget.Module.CSS_FOOTER
855
 
    * @static
856
 
    * @final
857
 
    * @type String
858
 
    */
859
 
    Module.CSS_FOOTER = "ft";
860
 
    
861
 
    /**
862
 
    * Constant representing the url for the "src" attribute of the iframe 
863
 
    * used to monitor changes to the browser's base font size
864
 
    * @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
865
 
    * @static
866
 
    * @final
867
 
    * @type String
868
 
    */
869
 
    Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
870
 
 
871
 
    /**
872
 
    * Constant representing the buffer amount (in pixels) to use when positioning
873
 
    * the text resize monitor offscreen. The resize monitor is positioned
874
 
    * offscreen by an amount eqaul to its offsetHeight + the buffer value.
875
 
    * 
876
 
    * @property YAHOO.widget.Module.RESIZE_MONITOR_BUFFER
877
 
    * @static
878
 
    * @type Number
879
 
    */
880
 
    // Set to 1, to work around pixel offset in IE8, which increases when zoom is used
881
 
    Module.RESIZE_MONITOR_BUFFER = 1;
882
 
 
883
 
    /**
884
 
    * Singleton CustomEvent fired when the font size is changed in the browser.
885
 
    * Opera's "zoom" functionality currently does not support text 
886
 
    * size detection.
887
 
    * @event YAHOO.widget.Module.textResizeEvent
888
 
    */
889
 
    Module.textResizeEvent = new CustomEvent("textResize");
890
 
 
891
 
    /**
892
 
     * Helper utility method, which forces a document level 
893
 
     * redraw for Opera, which can help remove repaint
894
 
     * irregularities after applying DOM changes.
895
 
     *
896
 
     * @method YAHOO.widget.Module.forceDocumentRedraw
897
 
     * @static
898
 
     */
899
 
    Module.forceDocumentRedraw = function() {
900
 
        var docEl = document.documentElement;
901
 
        if (docEl) {
902
 
            docEl.className += " ";
903
 
            docEl.className = YAHOO.lang.trim(docEl.className);
904
 
        }
905
 
    };
906
 
 
907
 
    function createModuleTemplate() {
908
 
 
909
 
        if (!m_oModuleTemplate) {
910
 
            m_oModuleTemplate = document.createElement("div");
911
 
            
912
 
            m_oModuleTemplate.innerHTML = ("<div class=\"" + 
913
 
                Module.CSS_HEADER + "\"></div>" + "<div class=\"" + 
914
 
                Module.CSS_BODY + "\"></div><div class=\"" + 
915
 
                Module.CSS_FOOTER + "\"></div>");
916
 
 
917
 
            m_oHeaderTemplate = m_oModuleTemplate.firstChild;
918
 
            m_oBodyTemplate = m_oHeaderTemplate.nextSibling;
919
 
            m_oFooterTemplate = m_oBodyTemplate.nextSibling;
920
 
        }
921
 
 
922
 
        return m_oModuleTemplate;
923
 
    }
924
 
 
925
 
    function createHeader() {
926
 
        if (!m_oHeaderTemplate) {
927
 
            createModuleTemplate();
928
 
        }
929
 
        return (m_oHeaderTemplate.cloneNode(false));
930
 
    }
931
 
 
932
 
    function createBody() {
933
 
        if (!m_oBodyTemplate) {
934
 
            createModuleTemplate();
935
 
        }
936
 
        return (m_oBodyTemplate.cloneNode(false));
937
 
    }
938
 
 
939
 
    function createFooter() {
940
 
        if (!m_oFooterTemplate) {
941
 
            createModuleTemplate();
942
 
        }
943
 
        return (m_oFooterTemplate.cloneNode(false));
944
 
    }
945
 
 
946
 
    Module.prototype = {
947
 
 
948
 
        /**
949
 
        * The class's constructor function
950
 
        * @property contructor
951
 
        * @type Function
952
 
        */
953
 
        constructor: Module,
954
 
        
955
 
        /**
956
 
        * The main module element that contains the header, body, and footer
957
 
        * @property element
958
 
        * @type HTMLElement
959
 
        */
960
 
        element: null,
961
 
 
962
 
        /**
963
 
        * The header element, denoted with CSS class "hd"
964
 
        * @property header
965
 
        * @type HTMLElement
966
 
        */
967
 
        header: null,
968
 
 
969
 
        /**
970
 
        * The body element, denoted with CSS class "bd"
971
 
        * @property body
972
 
        * @type HTMLElement
973
 
        */
974
 
        body: null,
975
 
 
976
 
        /**
977
 
        * The footer element, denoted with CSS class "ft"
978
 
        * @property footer
979
 
        * @type HTMLElement
980
 
        */
981
 
        footer: null,
982
 
 
983
 
        /**
984
 
        * The id of the element
985
 
        * @property id
986
 
        * @type String
987
 
        */
988
 
        id: null,
989
 
 
990
 
        /**
991
 
        * A string representing the root path for all images created by
992
 
        * a Module instance.
993
 
        * @deprecated It is recommend that any images for a Module be applied
994
 
        * via CSS using the "background-image" property.
995
 
        * @property imageRoot
996
 
        * @type String
997
 
        */
998
 
        imageRoot: Module.IMG_ROOT,
999
 
 
1000
 
        /**
1001
 
        * Initializes the custom events for Module which are fired 
1002
 
        * automatically at appropriate times by the Module class.
1003
 
        * @method initEvents
1004
 
        */
1005
 
        initEvents: function () {
1006
 
 
1007
 
            var SIGNATURE = CustomEvent.LIST;
1008
 
 
1009
 
            /**
1010
 
            * CustomEvent fired prior to class initalization.
1011
 
            * @event beforeInitEvent
1012
 
            * @param {class} classRef class reference of the initializing 
1013
 
            * class, such as this.beforeInitEvent.fire(Module)
1014
 
            */
1015
 
            this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT);
1016
 
            this.beforeInitEvent.signature = SIGNATURE;
1017
 
 
1018
 
            /**
1019
 
            * CustomEvent fired after class initalization.
1020
 
            * @event initEvent
1021
 
            * @param {class} classRef class reference of the initializing 
1022
 
            * class, such as this.beforeInitEvent.fire(Module)
1023
 
            */  
1024
 
            this.initEvent = this.createEvent(EVENT_TYPES.INIT);
1025
 
            this.initEvent.signature = SIGNATURE;
1026
 
 
1027
 
            /**
1028
 
            * CustomEvent fired when the Module is appended to the DOM
1029
 
            * @event appendEvent
1030
 
            */
1031
 
            this.appendEvent = this.createEvent(EVENT_TYPES.APPEND);
1032
 
            this.appendEvent.signature = SIGNATURE;
1033
 
 
1034
 
            /**
1035
 
            * CustomEvent fired before the Module is rendered
1036
 
            * @event beforeRenderEvent
1037
 
            */
1038
 
            this.beforeRenderEvent = this.createEvent(EVENT_TYPES.BEFORE_RENDER);
1039
 
            this.beforeRenderEvent.signature = SIGNATURE;
1040
 
        
1041
 
            /**
1042
 
            * CustomEvent fired after the Module is rendered
1043
 
            * @event renderEvent
1044
 
            */
1045
 
            this.renderEvent = this.createEvent(EVENT_TYPES.RENDER);
1046
 
            this.renderEvent.signature = SIGNATURE;
1047
 
        
1048
 
            /**
1049
 
            * CustomEvent fired when the header content of the Module 
1050
 
            * is modified
1051
 
            * @event changeHeaderEvent
1052
 
            * @param {String/HTMLElement} content String/element representing 
1053
 
            * the new header content
1054
 
            */
1055
 
            this.changeHeaderEvent = this.createEvent(EVENT_TYPES.CHANGE_HEADER);
1056
 
            this.changeHeaderEvent.signature = SIGNATURE;
1057
 
            
1058
 
            /**
1059
 
            * CustomEvent fired when the body content of the Module is modified
1060
 
            * @event changeBodyEvent
1061
 
            * @param {String/HTMLElement} content String/element representing 
1062
 
            * the new body content
1063
 
            */  
1064
 
            this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY);
1065
 
            this.changeBodyEvent.signature = SIGNATURE;
1066
 
            
1067
 
            /**
1068
 
            * CustomEvent fired when the footer content of the Module 
1069
 
            * is modified
1070
 
            * @event changeFooterEvent
1071
 
            * @param {String/HTMLElement} content String/element representing 
1072
 
            * the new footer content
1073
 
            */
1074
 
            this.changeFooterEvent = this.createEvent(EVENT_TYPES.CHANGE_FOOTER);
1075
 
            this.changeFooterEvent.signature = SIGNATURE;
1076
 
        
1077
 
            /**
1078
 
            * CustomEvent fired when the content of the Module is modified
1079
 
            * @event changeContentEvent
1080
 
            */
1081
 
            this.changeContentEvent = this.createEvent(EVENT_TYPES.CHANGE_CONTENT);
1082
 
            this.changeContentEvent.signature = SIGNATURE;
1083
 
 
1084
 
            /**
1085
 
            * CustomEvent fired when the Module is destroyed
1086
 
            * @event destroyEvent
1087
 
            */
1088
 
            this.destroyEvent = this.createEvent(EVENT_TYPES.DESTORY);
1089
 
            this.destroyEvent.signature = SIGNATURE;
1090
 
 
1091
 
            /**
1092
 
            * CustomEvent fired before the Module is shown
1093
 
            * @event beforeShowEvent
1094
 
            */
1095
 
            this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW);
1096
 
            this.beforeShowEvent.signature = SIGNATURE;
1097
 
 
1098
 
            /**
1099
 
            * CustomEvent fired after the Module is shown
1100
 
            * @event showEvent
1101
 
            */
1102
 
            this.showEvent = this.createEvent(EVENT_TYPES.SHOW);
1103
 
            this.showEvent.signature = SIGNATURE;
1104
 
 
1105
 
            /**
1106
 
            * CustomEvent fired before the Module is hidden
1107
 
            * @event beforeHideEvent
1108
 
            */
1109
 
            this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE);
1110
 
            this.beforeHideEvent.signature = SIGNATURE;
1111
 
 
1112
 
            /**
1113
 
            * CustomEvent fired after the Module is hidden
1114
 
            * @event hideEvent
1115
 
            */
1116
 
            this.hideEvent = this.createEvent(EVENT_TYPES.HIDE);
1117
 
            this.hideEvent.signature = SIGNATURE;
1118
 
        }, 
1119
 
 
1120
 
        /**
1121
 
        * String representing the current user-agent platform
1122
 
        * @property platform
1123
 
        * @type String
1124
 
        */
1125
 
        platform: function () {
1126
 
            var ua = navigator.userAgent.toLowerCase();
1127
 
 
1128
 
            if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
1129
 
                return "windows";
1130
 
            } else if (ua.indexOf("macintosh") != -1) {
1131
 
                return "mac";
1132
 
            } else {
1133
 
                return false;
1134
 
            }
1135
 
        }(),
1136
 
        
1137
 
        /**
1138
 
        * String representing the user-agent of the browser
1139
 
        * @deprecated Use YAHOO.env.ua
1140
 
        * @property browser
1141
 
        * @type String
1142
 
        */
1143
 
        browser: function () {
1144
 
            var ua = navigator.userAgent.toLowerCase();
1145
 
            /*
1146
 
                 Check Opera first in case of spoof and check Safari before
1147
 
                 Gecko since Safari's user agent string includes "like Gecko"
1148
 
            */
1149
 
            if (ua.indexOf('opera') != -1) { 
1150
 
                return 'opera';
1151
 
            } else if (ua.indexOf('msie 7') != -1) {
1152
 
                return 'ie7';
1153
 
            } else if (ua.indexOf('msie') != -1) {
1154
 
                return 'ie';
1155
 
            } else if (ua.indexOf('safari') != -1) { 
1156
 
                return 'safari';
1157
 
            } else if (ua.indexOf('gecko') != -1) {
1158
 
                return 'gecko';
1159
 
            } else {
1160
 
                return false;
1161
 
            }
1162
 
        }(),
1163
 
        
1164
 
        /**
1165
 
        * Boolean representing whether or not the current browsing context is 
1166
 
        * secure (https)
1167
 
        * @property isSecure
1168
 
        * @type Boolean
1169
 
        */
1170
 
        isSecure: function () {
1171
 
            if (window.location.href.toLowerCase().indexOf("https") === 0) {
1172
 
                return true;
1173
 
            } else {
1174
 
                return false;
1175
 
            }
1176
 
        }(),
1177
 
        
1178
 
        /**
1179
 
        * Initializes the custom events for Module which are fired 
1180
 
        * automatically at appropriate times by the Module class.
1181
 
        */
1182
 
        initDefaultConfig: function () {
1183
 
            // Add properties //
1184
 
            /**
1185
 
            * Specifies whether the Module is visible on the page.
1186
 
            * @config visible
1187
 
            * @type Boolean
1188
 
            * @default true
1189
 
            */
1190
 
            this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, {
1191
 
                handler: this.configVisible, 
1192
 
                value: DEFAULT_CONFIG.VISIBLE.value, 
1193
 
                validator: DEFAULT_CONFIG.VISIBLE.validator
1194
 
            });
1195
 
 
1196
 
            /**
1197
 
            * <p>
1198
 
            * Object or array of objects representing the ContainerEffect 
1199
 
            * classes that are active for animating the container.
1200
 
            * </p>
1201
 
            * <p>
1202
 
            * <strong>NOTE:</strong> Although this configuration 
1203
 
            * property is introduced at the Module level, an out of the box
1204
 
            * implementation is not shipped for the Module class so setting
1205
 
            * the proroperty on the Module class has no effect. The Overlay 
1206
 
            * class is the first class to provide out of the box ContainerEffect 
1207
 
            * support.
1208
 
            * </p>
1209
 
            * @config effect
1210
 
            * @type Object
1211
 
            * @default null
1212
 
            */
1213
 
            this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, {
1214
 
                suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent, 
1215
 
                supercedes: DEFAULT_CONFIG.EFFECT.supercedes
1216
 
            });
1217
 
 
1218
 
            /**
1219
 
            * Specifies whether to create a special proxy iframe to monitor 
1220
 
            * for user font resizing in the document
1221
 
            * @config monitorresize
1222
 
            * @type Boolean
1223
 
            * @default true
1224
 
            */
1225
 
            this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, {
1226
 
                handler: this.configMonitorResize,
1227
 
                value: DEFAULT_CONFIG.MONITOR_RESIZE.value
1228
 
            });
1229
 
 
1230
 
            /**
1231
 
            * Specifies if the module should be rendered as the first child 
1232
 
            * of document.body or appended as the last child when render is called
1233
 
            * with document.body as the "appendToNode".
1234
 
            * <p>
1235
 
            * Appending to the body while the DOM is still being constructed can 
1236
 
            * lead to Operation Aborted errors in IE hence this flag is set to 
1237
 
            * false by default.
1238
 
            * </p>
1239
 
            * 
1240
 
            * @config appendtodocumentbody
1241
 
            * @type Boolean
1242
 
            * @default false
1243
 
            */
1244
 
            this.cfg.addProperty(DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.key, {
1245
 
                value: DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.value
1246
 
            });
1247
 
        },
1248
 
 
1249
 
        /**
1250
 
        * The Module class's initialization method, which is executed for
1251
 
        * Module and all of its subclasses. This method is automatically 
1252
 
        * called by the constructor, and  sets up all DOM references for 
1253
 
        * pre-existing markup, and creates required markup if it is not 
1254
 
        * already present.
1255
 
        * <p>
1256
 
        * If the element passed in does not have an id, one will be generated
1257
 
        * for it.
1258
 
        * </p>
1259
 
        * @method init
1260
 
        * @param {String} el The element ID representing the Module <em>OR</em>
1261
 
        * @param {HTMLElement} el The element representing the Module
1262
 
        * @param {Object} userConfig The configuration Object literal 
1263
 
        * containing the configuration that should be set for this module. 
1264
 
        * See configuration documentation for more details.
1265
 
        */
1266
 
        init: function (el, userConfig) {
1267
 
 
1268
 
            var elId, child;
1269
 
 
1270
 
            this.initEvents();
1271
 
            this.beforeInitEvent.fire(Module);
1272
 
 
1273
 
            /**
1274
 
            * The Module's Config object used for monitoring 
1275
 
            * configuration properties.
1276
 
            * @property cfg
1277
 
            * @type YAHOO.util.Config
1278
 
            */
1279
 
            this.cfg = new Config(this);
1280
 
 
1281
 
            if (this.isSecure) {
1282
 
                this.imageRoot = Module.IMG_ROOT_SSL;
1283
 
            }
1284
 
 
1285
 
            if (typeof el == "string") {
1286
 
                elId = el;
1287
 
                el = document.getElementById(el);
1288
 
                if (! el) {
1289
 
                    el = (createModuleTemplate()).cloneNode(false);
1290
 
                    el.id = elId;
1291
 
                }
1292
 
            }
1293
 
 
1294
 
            this.id = Dom.generateId(el);
1295
 
            this.element = el;
1296
 
 
1297
 
            child = this.element.firstChild;
1298
 
 
1299
 
            if (child) {
1300
 
                var fndHd = false, fndBd = false, fndFt = false;
1301
 
                do {
1302
 
                    // We're looking for elements
1303
 
                    if (1 == child.nodeType) {
1304
 
                        if (!fndHd && Dom.hasClass(child, Module.CSS_HEADER)) {
1305
 
                            this.header = child;
1306
 
                            fndHd = true;
1307
 
                        } else if (!fndBd && Dom.hasClass(child, Module.CSS_BODY)) {
1308
 
                            this.body = child;
1309
 
                            fndBd = true;
1310
 
                        } else if (!fndFt && Dom.hasClass(child, Module.CSS_FOOTER)){
1311
 
                            this.footer = child;
1312
 
                            fndFt = true;
1313
 
                        }
1314
 
                    }
1315
 
                } while ((child = child.nextSibling));
1316
 
            }
1317
 
 
1318
 
            this.initDefaultConfig();
1319
 
 
1320
 
            Dom.addClass(this.element, Module.CSS_MODULE);
1321
 
 
1322
 
            if (userConfig) {
1323
 
                this.cfg.applyConfig(userConfig, true);
1324
 
            }
1325
 
 
1326
 
            /*
1327
 
                Subscribe to the fireQueue() method of Config so that any 
1328
 
                queued configuration changes are excecuted upon render of 
1329
 
                the Module
1330
 
            */ 
1331
 
 
1332
 
            if (!Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) {
1333
 
                this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
1334
 
            }
1335
 
 
1336
 
            this.initEvent.fire(Module);
1337
 
        },
1338
 
 
1339
 
        /**
1340
 
        * Initialize an empty IFRAME that is placed out of the visible area 
1341
 
        * that can be used to detect text resize.
1342
 
        * @method initResizeMonitor
1343
 
        */
1344
 
        initResizeMonitor: function () {
1345
 
 
1346
 
            var isGeckoWin = (UA.gecko && this.platform == "windows");
1347
 
            if (isGeckoWin) {
1348
 
                // Help prevent spinning loading icon which 
1349
 
                // started with FireFox 2.0.0.8/Win
1350
 
                var self = this;
1351
 
                setTimeout(function(){self._initResizeMonitor();}, 0);
1352
 
            } else {
1353
 
                this._initResizeMonitor();
1354
 
            }
1355
 
        },
1356
 
 
1357
 
        /**
1358
 
         * Create and initialize the text resize monitoring iframe.
1359
 
         * 
1360
 
         * @protected
1361
 
         * @method _initResizeMonitor
1362
 
         */
1363
 
        _initResizeMonitor : function() {
1364
 
 
1365
 
            var oDoc, 
1366
 
                oIFrame, 
1367
 
                sHTML;
1368
 
 
1369
 
            function fireTextResize() {
1370
 
                Module.textResizeEvent.fire();
1371
 
            }
1372
 
 
1373
 
            if (!UA.opera) {
1374
 
                oIFrame = Dom.get("_yuiResizeMonitor");
1375
 
 
1376
 
                var supportsCWResize = this._supportsCWResize();
1377
 
 
1378
 
                if (!oIFrame) {
1379
 
                    oIFrame = document.createElement("iframe");
1380
 
 
1381
 
                    if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && UA.ie) {
1382
 
                        oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL;
1383
 
                    }
1384
 
 
1385
 
                    if (!supportsCWResize) {
1386
 
                        // Can't monitor on contentWindow, so fire from inside iframe
1387
 
                        sHTML = ["<html><head><script ",
1388
 
                                 "type=\"text/javascript\">",
1389
 
                                 "window.onresize=function(){window.parent.",
1390
 
                                 "YAHOO.widget.Module.textResizeEvent.",
1391
 
                                 "fire();};<",
1392
 
                                 "\/script></head>",
1393
 
                                 "<body></body></html>"].join('');
1394
 
 
1395
 
                        oIFrame.src = "data:text/html;charset=utf-8," + encodeURIComponent(sHTML);
1396
 
                    }
1397
 
 
1398
 
                    oIFrame.id = "_yuiResizeMonitor";
1399
 
                    oIFrame.title = "Text Resize Monitor";
1400
 
                    /*
1401
 
                        Need to set "position" property before inserting the 
1402
 
                        iframe into the document or Safari's status bar will 
1403
 
                        forever indicate the iframe is loading 
1404
 
                        (See SourceForge bug #1723064)
1405
 
                    */
1406
 
                    oIFrame.style.position = "absolute";
1407
 
                    oIFrame.style.visibility = "hidden";
1408
 
 
1409
 
                    var db = document.body,
1410
 
                        fc = db.firstChild;
1411
 
                    if (fc) {
1412
 
                        db.insertBefore(oIFrame, fc);
1413
 
                    } else {
1414
 
                        db.appendChild(oIFrame);
1415
 
                    }
1416
 
 
1417
 
                    oIFrame.style.width = "2em";
1418
 
                    oIFrame.style.height = "2em";
1419
 
                    oIFrame.style.top = (-1 * (oIFrame.offsetHeight + Module.RESIZE_MONITOR_BUFFER)) + "px";
1420
 
                    oIFrame.style.left = "0";
1421
 
                    oIFrame.style.borderWidth = "0";
1422
 
                    oIFrame.style.visibility = "visible";
1423
 
 
1424
 
                    /*
1425
 
                       Don't open/close the document for Gecko like we used to, since it
1426
 
                       leads to duplicate cookies. (See SourceForge bug #1721755)
1427
 
                    */
1428
 
                    if (UA.webkit) {
1429
 
                        oDoc = oIFrame.contentWindow.document;
1430
 
                        oDoc.open();
1431
 
                        oDoc.close();
1432
 
                    }
1433
 
                }
1434
 
 
1435
 
                if (oIFrame && oIFrame.contentWindow) {
1436
 
                    Module.textResizeEvent.subscribe(this.onDomResize, this, true);
1437
 
 
1438
 
                    if (!Module.textResizeInitialized) {
1439
 
                        if (supportsCWResize) {
1440
 
                            if (!Event.on(oIFrame.contentWindow, "resize", fireTextResize)) {
1441
 
                                /*
1442
 
                                     This will fail in IE if document.domain has 
1443
 
                                     changed, so we must change the listener to 
1444
 
                                     use the oIFrame element instead
1445
 
                                */
1446
 
                                Event.on(oIFrame, "resize", fireTextResize);
1447
 
                            }
1448
 
                        }
1449
 
                        Module.textResizeInitialized = true;
1450
 
                    }
1451
 
                    this.resizeMonitor = oIFrame;
1452
 
                }
1453
 
            }
1454
 
        },
1455
 
 
1456
 
        /**
1457
 
         * Text resize monitor helper method.
1458
 
         * Determines if the browser supports resize events on iframe content windows.
1459
 
         * 
1460
 
         * @private
1461
 
         * @method _supportsCWResize
1462
 
         */
1463
 
        _supportsCWResize : function() {
1464
 
            /*
1465
 
                Gecko 1.8.0 (FF1.5), 1.8.1.0-5 (FF2) won't fire resize on contentWindow.
1466
 
                Gecko 1.8.1.6+ (FF2.0.0.6+) and all other browsers will fire resize on contentWindow.
1467
 
 
1468
 
                We don't want to start sniffing for patch versions, so fire textResize the same
1469
 
                way on all FF2 flavors
1470
 
             */
1471
 
            var bSupported = true;
1472
 
            if (UA.gecko && UA.gecko <= 1.8) {
1473
 
                bSupported = false;
1474
 
            }
1475
 
            return bSupported;
1476
 
        },
1477
 
 
1478
 
        /**
1479
 
        * Event handler fired when the resize monitor element is resized.
1480
 
        * @method onDomResize
1481
 
        * @param {DOMEvent} e The DOM resize event
1482
 
        * @param {Object} obj The scope object passed to the handler
1483
 
        */
1484
 
        onDomResize: function (e, obj) {
1485
 
 
1486
 
            var nTop = -1 * (this.resizeMonitor.offsetHeight + Module.RESIZE_MONITOR_BUFFER);
1487
 
 
1488
 
            this.resizeMonitor.style.top = nTop + "px";
1489
 
            this.resizeMonitor.style.left = "0";
1490
 
        },
1491
 
 
1492
 
        /**
1493
 
        * Sets the Module's header content to the string specified, or appends 
1494
 
        * the passed element to the header. If no header is present, one will 
1495
 
        * be automatically created. An empty string can be passed to the method
1496
 
        * to clear the contents of the header.
1497
 
        * 
1498
 
        * @method setHeader
1499
 
        * @param {String} headerContent The string used to set the header.
1500
 
        * As a convenience, non HTMLElement objects can also be passed into 
1501
 
        * the method, and will be treated as strings, with the header innerHTML
1502
 
        * set to their default toString implementations.
1503
 
        * <em>OR</em>
1504
 
        * @param {HTMLElement} headerContent The HTMLElement to append to 
1505
 
        * <em>OR</em>
1506
 
        * @param {DocumentFragment} headerContent The document fragment 
1507
 
        * containing elements which are to be added to the header
1508
 
        */
1509
 
        setHeader: function (headerContent) {
1510
 
            var oHeader = this.header || (this.header = createHeader());
1511
 
 
1512
 
            if (headerContent.nodeName) {
1513
 
                oHeader.innerHTML = "";
1514
 
                oHeader.appendChild(headerContent);
1515
 
            } else {
1516
 
                oHeader.innerHTML = headerContent;
1517
 
            }
1518
 
 
1519
 
            this.changeHeaderEvent.fire(headerContent);
1520
 
            this.changeContentEvent.fire();
1521
 
 
1522
 
        },
1523
 
 
1524
 
        /**
1525
 
        * Appends the passed element to the header. If no header is present, 
1526
 
        * one will be automatically created.
1527
 
        * @method appendToHeader
1528
 
        * @param {HTMLElement | DocumentFragment} element The element to 
1529
 
        * append to the header. In the case of a document fragment, the
1530
 
        * children of the fragment will be appended to the header.
1531
 
        */
1532
 
        appendToHeader: function (element) {
1533
 
            var oHeader = this.header || (this.header = createHeader());
1534
 
 
1535
 
            oHeader.appendChild(element);
1536
 
 
1537
 
            this.changeHeaderEvent.fire(element);
1538
 
            this.changeContentEvent.fire();
1539
 
 
1540
 
        },
1541
 
 
1542
 
        /**
1543
 
        * Sets the Module's body content to the HTML specified. 
1544
 
        * 
1545
 
        * If no body is present, one will be automatically created. 
1546
 
        * 
1547
 
        * An empty string can be passed to the method to clear the contents of the body.
1548
 
        * @method setBody
1549
 
        * @param {String} bodyContent The HTML used to set the body. 
1550
 
        * As a convenience, non HTMLElement objects can also be passed into 
1551
 
        * the method, and will be treated as strings, with the body innerHTML
1552
 
        * set to their default toString implementations.
1553
 
        * <em>OR</em>
1554
 
        * @param {HTMLElement} bodyContent The HTMLElement to add as the first and only
1555
 
        * child of the body element.
1556
 
        * <em>OR</em>
1557
 
        * @param {DocumentFragment} bodyContent The document fragment 
1558
 
        * containing elements which are to be added to the body
1559
 
        */
1560
 
        setBody: function (bodyContent) {
1561
 
            var oBody = this.body || (this.body = createBody());
1562
 
 
1563
 
            if (bodyContent.nodeName) {
1564
 
                oBody.innerHTML = "";
1565
 
                oBody.appendChild(bodyContent);
1566
 
            } else {
1567
 
                oBody.innerHTML = bodyContent;
1568
 
            }
1569
 
 
1570
 
            this.changeBodyEvent.fire(bodyContent);
1571
 
            this.changeContentEvent.fire();
1572
 
        },
1573
 
 
1574
 
        /**
1575
 
        * Appends the passed element to the body. If no body is present, one 
1576
 
        * will be automatically created.
1577
 
        * @method appendToBody
1578
 
        * @param {HTMLElement | DocumentFragment} element The element to 
1579
 
        * append to the body. In the case of a document fragment, the
1580
 
        * children of the fragment will be appended to the body.
1581
 
        * 
1582
 
        */
1583
 
        appendToBody: function (element) {
1584
 
            var oBody = this.body || (this.body = createBody());
1585
 
        
1586
 
            oBody.appendChild(element);
1587
 
 
1588
 
            this.changeBodyEvent.fire(element);
1589
 
            this.changeContentEvent.fire();
1590
 
 
1591
 
        },
1592
 
        
1593
 
        /**
1594
 
        * Sets the Module's footer content to the HTML specified, or appends 
1595
 
        * the passed element to the footer. If no footer is present, one will 
1596
 
        * be automatically created. An empty string can be passed to the method
1597
 
        * to clear the contents of the footer.
1598
 
        * @method setFooter
1599
 
        * @param {String} footerContent The HTML used to set the footer 
1600
 
        * As a convenience, non HTMLElement objects can also be passed into 
1601
 
        * the method, and will be treated as strings, with the footer innerHTML
1602
 
        * set to their default toString implementations.
1603
 
        * <em>OR</em>
1604
 
        * @param {HTMLElement} footerContent The HTMLElement to append to 
1605
 
        * the footer
1606
 
        * <em>OR</em>
1607
 
        * @param {DocumentFragment} footerContent The document fragment containing 
1608
 
        * elements which are to be added to the footer
1609
 
        */
1610
 
        setFooter: function (footerContent) {
1611
 
 
1612
 
            var oFooter = this.footer || (this.footer = createFooter());
1613
 
 
1614
 
            if (footerContent.nodeName) {
1615
 
                oFooter.innerHTML = "";
1616
 
                oFooter.appendChild(footerContent);
1617
 
            } else {
1618
 
                oFooter.innerHTML = footerContent;
1619
 
            }
1620
 
 
1621
 
            this.changeFooterEvent.fire(footerContent);
1622
 
            this.changeContentEvent.fire();
1623
 
        },
1624
 
 
1625
 
        /**
1626
 
        * Appends the passed element to the footer. If no footer is present, 
1627
 
        * one will be automatically created.
1628
 
        * @method appendToFooter
1629
 
        * @param {HTMLElement | DocumentFragment} element The element to 
1630
 
        * append to the footer. In the case of a document fragment, the
1631
 
        * children of the fragment will be appended to the footer
1632
 
        */
1633
 
        appendToFooter: function (element) {
1634
 
 
1635
 
            var oFooter = this.footer || (this.footer = createFooter());
1636
 
 
1637
 
            oFooter.appendChild(element);
1638
 
 
1639
 
            this.changeFooterEvent.fire(element);
1640
 
            this.changeContentEvent.fire();
1641
 
 
1642
 
        },
1643
 
 
1644
 
        /**
1645
 
        * Renders the Module by inserting the elements that are not already 
1646
 
        * in the main Module into their correct places. Optionally appends 
1647
 
        * the Module to the specified node prior to the render's execution. 
1648
 
        * <p>
1649
 
        * For Modules without existing markup, the appendToNode argument 
1650
 
        * is REQUIRED. If this argument is ommitted and the current element is 
1651
 
        * not present in the document, the function will return false, 
1652
 
        * indicating that the render was a failure.
1653
 
        * </p>
1654
 
        * <p>
1655
 
        * NOTE: As of 2.3.1, if the appendToNode is the document's body element
1656
 
        * then the module is rendered as the first child of the body element, 
1657
 
        * and not appended to it, to avoid Operation Aborted errors in IE when 
1658
 
        * rendering the module before window's load event is fired. You can 
1659
 
        * use the appendtodocumentbody configuration property to change this 
1660
 
        * to append to document.body if required.
1661
 
        * </p>
1662
 
        * @method render
1663
 
        * @param {String} appendToNode The element id to which the Module 
1664
 
        * should be appended to prior to rendering <em>OR</em>
1665
 
        * @param {HTMLElement} appendToNode The element to which the Module 
1666
 
        * should be appended to prior to rendering
1667
 
        * @param {HTMLElement} moduleElement OPTIONAL. The element that 
1668
 
        * represents the actual Standard Module container.
1669
 
        * @return {Boolean} Success or failure of the render
1670
 
        */
1671
 
        render: function (appendToNode, moduleElement) {
1672
 
 
1673
 
            var me = this,
1674
 
                firstChild;
1675
 
 
1676
 
            function appendTo(parentNode) {
1677
 
                if (typeof parentNode == "string") {
1678
 
                    parentNode = document.getElementById(parentNode);
1679
 
                }
1680
 
 
1681
 
                if (parentNode) {
1682
 
                    me._addToParent(parentNode, me.element);
1683
 
                    me.appendEvent.fire();
1684
 
                }
1685
 
            }
1686
 
 
1687
 
            this.beforeRenderEvent.fire();
1688
 
 
1689
 
            if (! moduleElement) {
1690
 
                moduleElement = this.element;
1691
 
            }
1692
 
 
1693
 
            if (appendToNode) {
1694
 
                appendTo(appendToNode);
1695
 
            } else { 
1696
 
                // No node was passed in. If the element is not already in the Dom, this fails
1697
 
                if (! Dom.inDocument(this.element)) {
1698
 
                    YAHOO.log("Render failed. Must specify appendTo node if " + " Module isn't already in the DOM.", "error");
1699
 
                    return false;
1700
 
                }
1701
 
            }
1702
 
 
1703
 
            // Need to get everything into the DOM if it isn't already
1704
 
            if (this.header && ! Dom.inDocument(this.header)) {
1705
 
                // There is a header, but it's not in the DOM yet. Need to add it.
1706
 
                firstChild = moduleElement.firstChild;
1707
 
                if (firstChild) {
1708
 
                    moduleElement.insertBefore(this.header, firstChild);
1709
 
                } else {
1710
 
                    moduleElement.appendChild(this.header);
1711
 
                }
1712
 
            }
1713
 
 
1714
 
            if (this.body && ! Dom.inDocument(this.body)) {
1715
 
                // There is a body, but it's not in the DOM yet. Need to add it.                
1716
 
                if (this.footer && Dom.isAncestor(this.moduleElement, this.footer)) {
1717
 
                    moduleElement.insertBefore(this.body, this.footer);
1718
 
                } else {
1719
 
                    moduleElement.appendChild(this.body);
1720
 
                }
1721
 
            }
1722
 
 
1723
 
            if (this.footer && ! Dom.inDocument(this.footer)) {
1724
 
                // There is a footer, but it's not in the DOM yet. Need to add it.
1725
 
                moduleElement.appendChild(this.footer);
1726
 
            }
1727
 
 
1728
 
            this.renderEvent.fire();
1729
 
            return true;
1730
 
        },
1731
 
 
1732
 
        /**
1733
 
        * Removes the Module element from the DOM and sets all child elements 
1734
 
        * to null.
1735
 
        * @method destroy
1736
 
        */
1737
 
        destroy: function () {
1738
 
 
1739
 
            var parent;
1740
 
 
1741
 
            if (this.element) {
1742
 
                Event.purgeElement(this.element, true);
1743
 
                parent = this.element.parentNode;
1744
 
            }
1745
 
 
1746
 
            if (parent) {
1747
 
                parent.removeChild(this.element);
1748
 
            }
1749
 
        
1750
 
            this.element = null;
1751
 
            this.header = null;
1752
 
            this.body = null;
1753
 
            this.footer = null;
1754
 
 
1755
 
            Module.textResizeEvent.unsubscribe(this.onDomResize, this);
1756
 
 
1757
 
            this.cfg.destroy();
1758
 
            this.cfg = null;
1759
 
 
1760
 
            this.destroyEvent.fire();
1761
 
        },
1762
 
 
1763
 
        /**
1764
 
        * Shows the Module element by setting the visible configuration 
1765
 
        * property to true. Also fires two events: beforeShowEvent prior to 
1766
 
        * the visibility change, and showEvent after.
1767
 
        * @method show
1768
 
        */
1769
 
        show: function () {
1770
 
            this.cfg.setProperty("visible", true);
1771
 
        },
1772
 
 
1773
 
        /**
1774
 
        * Hides the Module element by setting the visible configuration 
1775
 
        * property to false. Also fires two events: beforeHideEvent prior to 
1776
 
        * the visibility change, and hideEvent after.
1777
 
        * @method hide
1778
 
        */
1779
 
        hide: function () {
1780
 
            this.cfg.setProperty("visible", false);
1781
 
        },
1782
 
        
1783
 
        // BUILT-IN EVENT HANDLERS FOR MODULE //
1784
 
        /**
1785
 
        * Default event handler for changing the visibility property of a 
1786
 
        * Module. By default, this is achieved by switching the "display" style 
1787
 
        * between "block" and "none".
1788
 
        * This method is responsible for firing showEvent and hideEvent.
1789
 
        * @param {String} type The CustomEvent type (usually the property name)
1790
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
1791
 
        * handlers, args[0] will equal the newly applied value for the property.
1792
 
        * @param {Object} obj The scope object. For configuration handlers, 
1793
 
        * this will usually equal the owner.
1794
 
        * @method configVisible
1795
 
        */
1796
 
        configVisible: function (type, args, obj) {
1797
 
            var visible = args[0];
1798
 
            if (visible) {
1799
 
                this.beforeShowEvent.fire();
1800
 
                Dom.setStyle(this.element, "display", "block");
1801
 
                this.showEvent.fire();
1802
 
            } else {
1803
 
                this.beforeHideEvent.fire();
1804
 
                Dom.setStyle(this.element, "display", "none");
1805
 
                this.hideEvent.fire();
1806
 
            }
1807
 
        },
1808
 
 
1809
 
        /**
1810
 
        * Default event handler for the "monitorresize" configuration property
1811
 
        * @param {String} type The CustomEvent type (usually the property name)
1812
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
1813
 
        * handlers, args[0] will equal the newly applied value for the property.
1814
 
        * @param {Object} obj The scope object. For configuration handlers, 
1815
 
        * this will usually equal the owner.
1816
 
        * @method configMonitorResize
1817
 
        */
1818
 
        configMonitorResize: function (type, args, obj) {
1819
 
            var monitor = args[0];
1820
 
            if (monitor) {
1821
 
                this.initResizeMonitor();
1822
 
            } else {
1823
 
                Module.textResizeEvent.unsubscribe(this.onDomResize, this, true);
1824
 
                this.resizeMonitor = null;
1825
 
            }
1826
 
        },
1827
 
 
1828
 
        /**
1829
 
         * This method is a protected helper, used when constructing the DOM structure for the module 
1830
 
         * to account for situations which may cause Operation Aborted errors in IE. It should not 
1831
 
         * be used for general DOM construction.
1832
 
         * <p>
1833
 
         * If the parentNode is not document.body, the element is appended as the last element.
1834
 
         * </p>
1835
 
         * <p>
1836
 
         * If the parentNode is document.body the element is added as the first child to help
1837
 
         * prevent Operation Aborted errors in IE.
1838
 
         * </p>
1839
 
         *
1840
 
         * @param {parentNode} The HTML element to which the element will be added
1841
 
         * @param {element} The HTML element to be added to parentNode's children
1842
 
         * @method _addToParent
1843
 
         * @protected
1844
 
         */
1845
 
        _addToParent: function(parentNode, element) {
1846
 
            if (!this.cfg.getProperty("appendtodocumentbody") && parentNode === document.body && parentNode.firstChild) {
1847
 
                parentNode.insertBefore(element, parentNode.firstChild);
1848
 
            } else {
1849
 
                parentNode.appendChild(element);
1850
 
            }
1851
 
        },
1852
 
 
1853
 
        /**
1854
 
        * Returns a String representation of the Object.
1855
 
        * @method toString
1856
 
        * @return {String} The string representation of the Module
1857
 
        */
1858
 
        toString: function () {
1859
 
            return "Module " + this.id;
1860
 
        }
1861
 
    };
1862
 
 
1863
 
    YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
1864
 
 
1865
 
}());
1866
 
 
1867
 
(function () {
1868
 
 
1869
 
    /**
1870
 
    * Overlay is a Module that is absolutely positioned above the page flow. It 
1871
 
    * has convenience methods for positioning and sizing, as well as options for 
1872
 
    * controlling zIndex and constraining the Overlay's position to the current 
1873
 
    * visible viewport. Overlay also contains a dynamicly generated IFRAME which 
1874
 
    * is placed beneath it for Internet Explorer 6 and 5.x so that it will be 
1875
 
    * properly rendered above SELECT elements.
1876
 
    * @namespace YAHOO.widget
1877
 
    * @class Overlay
1878
 
    * @extends YAHOO.widget.Module
1879
 
    * @param {String} el The element ID representing the Overlay <em>OR</em>
1880
 
    * @param {HTMLElement} el The element representing the Overlay
1881
 
    * @param {Object} userConfig The configuration object literal containing 
1882
 
    * the configuration that should be set for this Overlay. See configuration 
1883
 
    * documentation for more details.
1884
 
    * @constructor
1885
 
    */
1886
 
    YAHOO.widget.Overlay = function (el, userConfig) {
1887
 
        YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
1888
 
    };
1889
 
 
1890
 
    var Lang = YAHOO.lang,
1891
 
        CustomEvent = YAHOO.util.CustomEvent,
1892
 
        Module = YAHOO.widget.Module,
1893
 
        Event = YAHOO.util.Event,
1894
 
        Dom = YAHOO.util.Dom,
1895
 
        Config = YAHOO.util.Config,
1896
 
        UA = YAHOO.env.ua,
1897
 
        Overlay = YAHOO.widget.Overlay,
1898
 
 
1899
 
        _SUBSCRIBE = "subscribe",
1900
 
        _UNSUBSCRIBE = "unsubscribe",
1901
 
        _CONTAINED = "contained",
1902
 
 
1903
 
        m_oIFrameTemplate,
1904
 
 
1905
 
        /**
1906
 
        * Constant representing the name of the Overlay's events
1907
 
        * @property EVENT_TYPES
1908
 
        * @private
1909
 
        * @final
1910
 
        * @type Object
1911
 
        */
1912
 
        EVENT_TYPES = {
1913
 
            "BEFORE_MOVE": "beforeMove",
1914
 
            "MOVE": "move"
1915
 
        },
1916
 
 
1917
 
        /**
1918
 
        * Constant representing the Overlay's configuration properties
1919
 
        * @property DEFAULT_CONFIG
1920
 
        * @private
1921
 
        * @final
1922
 
        * @type Object
1923
 
        */
1924
 
        DEFAULT_CONFIG = {
1925
 
 
1926
 
            "X": { 
1927
 
                key: "x", 
1928
 
                validator: Lang.isNumber, 
1929
 
                suppressEvent: true, 
1930
 
                supercedes: ["iframe"]
1931
 
            },
1932
 
 
1933
 
            "Y": { 
1934
 
                key: "y", 
1935
 
                validator: Lang.isNumber, 
1936
 
                suppressEvent: true, 
1937
 
                supercedes: ["iframe"]
1938
 
            },
1939
 
 
1940
 
            "XY": { 
1941
 
                key: "xy", 
1942
 
                suppressEvent: true, 
1943
 
                supercedes: ["iframe"] 
1944
 
            },
1945
 
 
1946
 
            "CONTEXT": { 
1947
 
                key: "context", 
1948
 
                suppressEvent: true, 
1949
 
                supercedes: ["iframe"] 
1950
 
            },
1951
 
 
1952
 
            "FIXED_CENTER": { 
1953
 
                key: "fixedcenter", 
1954
 
                value: false, 
1955
 
                supercedes: ["iframe", "visible"] 
1956
 
            },
1957
 
 
1958
 
            "WIDTH": { 
1959
 
                key: "width",
1960
 
                suppressEvent: true,
1961
 
                supercedes: ["context", "fixedcenter", "iframe"]
1962
 
            }, 
1963
 
 
1964
 
            "HEIGHT": { 
1965
 
                key: "height", 
1966
 
                suppressEvent: true, 
1967
 
                supercedes: ["context", "fixedcenter", "iframe"] 
1968
 
            },
1969
 
 
1970
 
            "AUTO_FILL_HEIGHT" : {
1971
 
                key: "autofillheight",
1972
 
                supercedes: ["height"],
1973
 
                value:"body"
1974
 
            },
1975
 
 
1976
 
            "ZINDEX": { 
1977
 
                key: "zindex", 
1978
 
                value: null 
1979
 
            },
1980
 
 
1981
 
            "CONSTRAIN_TO_VIEWPORT": { 
1982
 
                key: "constraintoviewport", 
1983
 
                value: false, 
1984
 
                validator: Lang.isBoolean, 
1985
 
                supercedes: ["iframe", "x", "y", "xy"]
1986
 
            }, 
1987
 
 
1988
 
            "IFRAME": { 
1989
 
                key: "iframe", 
1990
 
                value: (UA.ie == 6 ? true : false), 
1991
 
                validator: Lang.isBoolean, 
1992
 
                supercedes: ["zindex"] 
1993
 
            },
1994
 
 
1995
 
            "PREVENT_CONTEXT_OVERLAP": {
1996
 
                key: "preventcontextoverlap",
1997
 
                value: false,
1998
 
                validator: Lang.isBoolean,  
1999
 
                supercedes: ["constraintoviewport"]
2000
 
            }
2001
 
 
2002
 
        };
2003
 
 
2004
 
    /**
2005
 
    * The URL that will be placed in the iframe
2006
 
    * @property YAHOO.widget.Overlay.IFRAME_SRC
2007
 
    * @static
2008
 
    * @final
2009
 
    * @type String
2010
 
    */
2011
 
    Overlay.IFRAME_SRC = "javascript:false;";
2012
 
 
2013
 
    /**
2014
 
    * Number representing how much the iframe shim should be offset from each 
2015
 
    * side of an Overlay instance, in pixels.
2016
 
    * @property YAHOO.widget.Overlay.IFRAME_SRC
2017
 
    * @default 3
2018
 
    * @static
2019
 
    * @final
2020
 
    * @type Number
2021
 
    */
2022
 
    Overlay.IFRAME_OFFSET = 3;
2023
 
 
2024
 
    /**
2025
 
    * Number representing the minimum distance an Overlay instance should be 
2026
 
    * positioned relative to the boundaries of the browser's viewport, in pixels.
2027
 
    * @property YAHOO.widget.Overlay.VIEWPORT_OFFSET
2028
 
    * @default 10
2029
 
    * @static
2030
 
    * @final
2031
 
    * @type Number
2032
 
    */
2033
 
    Overlay.VIEWPORT_OFFSET = 10;
2034
 
 
2035
 
    /**
2036
 
    * Constant representing the top left corner of an element, used for 
2037
 
    * configuring the context element alignment
2038
 
    * @property YAHOO.widget.Overlay.TOP_LEFT
2039
 
    * @static
2040
 
    * @final
2041
 
    * @type String
2042
 
    */
2043
 
    Overlay.TOP_LEFT = "tl";
2044
 
 
2045
 
    /**
2046
 
    * Constant representing the top right corner of an element, used for 
2047
 
    * configuring the context element alignment
2048
 
    * @property YAHOO.widget.Overlay.TOP_RIGHT
2049
 
    * @static
2050
 
    * @final
2051
 
    * @type String
2052
 
    */
2053
 
    Overlay.TOP_RIGHT = "tr";
2054
 
 
2055
 
    /**
2056
 
    * Constant representing the top bottom left corner of an element, used for 
2057
 
    * configuring the context element alignment
2058
 
    * @property YAHOO.widget.Overlay.BOTTOM_LEFT
2059
 
    * @static
2060
 
    * @final
2061
 
    * @type String
2062
 
    */
2063
 
    Overlay.BOTTOM_LEFT = "bl";
2064
 
 
2065
 
    /**
2066
 
    * Constant representing the bottom right corner of an element, used for 
2067
 
    * configuring the context element alignment
2068
 
    * @property YAHOO.widget.Overlay.BOTTOM_RIGHT
2069
 
    * @static
2070
 
    * @final
2071
 
    * @type String
2072
 
    */
2073
 
    Overlay.BOTTOM_RIGHT = "br";
2074
 
 
2075
 
    /**
2076
 
    * Constant representing the default CSS class used for an Overlay
2077
 
    * @property YAHOO.widget.Overlay.CSS_OVERLAY
2078
 
    * @static
2079
 
    * @final
2080
 
    * @type String
2081
 
    */
2082
 
    Overlay.CSS_OVERLAY = "yui-overlay";
2083
 
 
2084
 
    /**
2085
 
     * Constant representing the names of the standard module elements
2086
 
     * used in the overlay.
2087
 
     * @property YAHOO.widget.Overlay.STD_MOD_RE
2088
 
     * @static
2089
 
     * @final
2090
 
     * @type RegExp
2091
 
     */
2092
 
    Overlay.STD_MOD_RE = /^\s*?(body|footer|header)\s*?$/i;
2093
 
 
2094
 
    /**
2095
 
    * A singleton CustomEvent used for reacting to the DOM event for 
2096
 
    * window scroll
2097
 
    * @event YAHOO.widget.Overlay.windowScrollEvent
2098
 
    */
2099
 
    Overlay.windowScrollEvent = new CustomEvent("windowScroll");
2100
 
 
2101
 
    /**
2102
 
    * A singleton CustomEvent used for reacting to the DOM event for
2103
 
    * window resize
2104
 
    * @event YAHOO.widget.Overlay.windowResizeEvent
2105
 
    */
2106
 
    Overlay.windowResizeEvent = new CustomEvent("windowResize");
2107
 
 
2108
 
    /**
2109
 
    * The DOM event handler used to fire the CustomEvent for window scroll
2110
 
    * @method YAHOO.widget.Overlay.windowScrollHandler
2111
 
    * @static
2112
 
    * @param {DOMEvent} e The DOM scroll event
2113
 
    */
2114
 
    Overlay.windowScrollHandler = function (e) {
2115
 
        var t = Event.getTarget(e);
2116
 
 
2117
 
        // - Webkit (Safari 2/3) and Opera 9.2x bubble scroll events from elements to window
2118
 
        // - FF2/3 and IE6/7, Opera 9.5x don't bubble scroll events from elements to window
2119
 
        // - IE doesn't recognize scroll registered on the document.
2120
 
        //
2121
 
        // Also, when document view is scrolled, IE doesn't provide a target, 
2122
 
        // rest of the browsers set target to window.document, apart from opera 
2123
 
        // which sets target to window.
2124
 
        if (!t || t === window || t === window.document) {
2125
 
            if (UA.ie) {
2126
 
 
2127
 
                if (! window.scrollEnd) {
2128
 
                    window.scrollEnd = -1;
2129
 
                }
2130
 
 
2131
 
                clearTimeout(window.scrollEnd);
2132
 
        
2133
 
                window.scrollEnd = setTimeout(function () { 
2134
 
                    Overlay.windowScrollEvent.fire(); 
2135
 
                }, 1);
2136
 
        
2137
 
            } else {
2138
 
                Overlay.windowScrollEvent.fire();
2139
 
            }
2140
 
        }
2141
 
    };
2142
 
 
2143
 
    /**
2144
 
    * The DOM event handler used to fire the CustomEvent for window resize
2145
 
    * @method YAHOO.widget.Overlay.windowResizeHandler
2146
 
    * @static
2147
 
    * @param {DOMEvent} e The DOM resize event
2148
 
    */
2149
 
    Overlay.windowResizeHandler = function (e) {
2150
 
 
2151
 
        if (UA.ie) {
2152
 
            if (! window.resizeEnd) {
2153
 
                window.resizeEnd = -1;
2154
 
            }
2155
 
 
2156
 
            clearTimeout(window.resizeEnd);
2157
 
 
2158
 
            window.resizeEnd = setTimeout(function () {
2159
 
                Overlay.windowResizeEvent.fire(); 
2160
 
            }, 100);
2161
 
        } else {
2162
 
            Overlay.windowResizeEvent.fire();
2163
 
        }
2164
 
    };
2165
 
 
2166
 
    /**
2167
 
    * A boolean that indicated whether the window resize and scroll events have 
2168
 
    * already been subscribed to.
2169
 
    * @property YAHOO.widget.Overlay._initialized
2170
 
    * @private
2171
 
    * @type Boolean
2172
 
    */
2173
 
    Overlay._initialized = null;
2174
 
 
2175
 
    if (Overlay._initialized === null) {
2176
 
        Event.on(window, "scroll", Overlay.windowScrollHandler);
2177
 
        Event.on(window, "resize", Overlay.windowResizeHandler);
2178
 
        Overlay._initialized = true;
2179
 
    }
2180
 
 
2181
 
    /**
2182
 
     * Internal map of special event types, which are provided
2183
 
     * by the instance. It maps the event type to the custom event 
2184
 
     * instance. Contains entries for the "windowScroll", "windowResize" and
2185
 
     * "textResize" static container events.
2186
 
     *
2187
 
     * @property YAHOO.widget.Overlay._TRIGGER_MAP
2188
 
     * @type Object
2189
 
     * @static
2190
 
     * @private
2191
 
     */
2192
 
    Overlay._TRIGGER_MAP = {
2193
 
        "windowScroll" : Overlay.windowScrollEvent,
2194
 
        "windowResize" : Overlay.windowResizeEvent,
2195
 
        "textResize"   : Module.textResizeEvent
2196
 
    };
2197
 
 
2198
 
    YAHOO.extend(Overlay, Module, {
2199
 
 
2200
 
        /**
2201
 
         * <p>
2202
 
         * Array of default event types which will trigger
2203
 
         * context alignment for the Overlay class.
2204
 
         * </p>
2205
 
         * <p>The array is empty by default for Overlay,
2206
 
         * but maybe populated in future releases, so classes extending
2207
 
         * Overlay which need to define their own set of CONTEXT_TRIGGERS
2208
 
         * should concatenate their super class's prototype.CONTEXT_TRIGGERS 
2209
 
         * value with their own array of values.
2210
 
         * </p>
2211
 
         * <p>
2212
 
         * E.g.:
2213
 
         * <code>CustomOverlay.prototype.CONTEXT_TRIGGERS = YAHOO.widget.Overlay.prototype.CONTEXT_TRIGGERS.concat(["windowScroll"]);</code>
2214
 
         * </p>
2215
 
         * 
2216
 
         * @property CONTEXT_TRIGGERS
2217
 
         * @type Array
2218
 
         * @final
2219
 
         */
2220
 
        CONTEXT_TRIGGERS : [],
2221
 
 
2222
 
        /**
2223
 
        * The Overlay initialization method, which is executed for Overlay and  
2224
 
        * all of its subclasses. This method is automatically called by the 
2225
 
        * constructor, and  sets up all DOM references for pre-existing markup, 
2226
 
        * and creates required markup if it is not already present.
2227
 
        * @method init
2228
 
        * @param {String} el The element ID representing the Overlay <em>OR</em>
2229
 
        * @param {HTMLElement} el The element representing the Overlay
2230
 
        * @param {Object} userConfig The configuration object literal 
2231
 
        * containing the configuration that should be set for this Overlay. 
2232
 
        * See configuration documentation for more details.
2233
 
        */
2234
 
        init: function (el, userConfig) {
2235
 
 
2236
 
            /*
2237
 
                 Note that we don't pass the user config in here yet because we
2238
 
                 only want it executed once, at the lowest subclass level
2239
 
            */
2240
 
 
2241
 
            Overlay.superclass.init.call(this, el/*, userConfig*/);
2242
 
 
2243
 
            this.beforeInitEvent.fire(Overlay);
2244
 
 
2245
 
            Dom.addClass(this.element, Overlay.CSS_OVERLAY);
2246
 
 
2247
 
            if (userConfig) {
2248
 
                this.cfg.applyConfig(userConfig, true);
2249
 
            }
2250
 
 
2251
 
            if (this.platform == "mac" && UA.gecko) {
2252
 
 
2253
 
                if (! Config.alreadySubscribed(this.showEvent,
2254
 
                    this.showMacGeckoScrollbars, this)) {
2255
 
 
2256
 
                    this.showEvent.subscribe(this.showMacGeckoScrollbars, 
2257
 
                        this, true);
2258
 
 
2259
 
                }
2260
 
 
2261
 
                if (! Config.alreadySubscribed(this.hideEvent, 
2262
 
                    this.hideMacGeckoScrollbars, this)) {
2263
 
 
2264
 
                    this.hideEvent.subscribe(this.hideMacGeckoScrollbars, 
2265
 
                        this, true);
2266
 
 
2267
 
                }
2268
 
            }
2269
 
 
2270
 
            this.initEvent.fire(Overlay);
2271
 
        },
2272
 
        
2273
 
        /**
2274
 
        * Initializes the custom events for Overlay which are fired  
2275
 
        * automatically at appropriate times by the Overlay class.
2276
 
        * @method initEvents
2277
 
        */
2278
 
        initEvents: function () {
2279
 
 
2280
 
            Overlay.superclass.initEvents.call(this);
2281
 
 
2282
 
            var SIGNATURE = CustomEvent.LIST;
2283
 
 
2284
 
            /**
2285
 
            * CustomEvent fired before the Overlay is moved.
2286
 
            * @event beforeMoveEvent
2287
 
            * @param {Number} x x coordinate
2288
 
            * @param {Number} y y coordinate
2289
 
            */
2290
 
            this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
2291
 
            this.beforeMoveEvent.signature = SIGNATURE;
2292
 
 
2293
 
            /**
2294
 
            * CustomEvent fired after the Overlay is moved.
2295
 
            * @event moveEvent
2296
 
            * @param {Number} x x coordinate
2297
 
            * @param {Number} y y coordinate
2298
 
            */
2299
 
            this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
2300
 
            this.moveEvent.signature = SIGNATURE;
2301
 
 
2302
 
        },
2303
 
        
2304
 
        /**
2305
 
        * Initializes the class's configurable properties which can be changed 
2306
 
        * using the Overlay's Config object (cfg).
2307
 
        * @method initDefaultConfig
2308
 
        */
2309
 
        initDefaultConfig: function () {
2310
 
    
2311
 
            Overlay.superclass.initDefaultConfig.call(this);
2312
 
 
2313
 
            var cfg = this.cfg;
2314
 
 
2315
 
            // Add overlay config properties //
2316
 
            
2317
 
            /**
2318
 
            * The absolute x-coordinate position of the Overlay
2319
 
            * @config x
2320
 
            * @type Number
2321
 
            * @default null
2322
 
            */
2323
 
            cfg.addProperty(DEFAULT_CONFIG.X.key, { 
2324
 
    
2325
 
                handler: this.configX, 
2326
 
                validator: DEFAULT_CONFIG.X.validator, 
2327
 
                suppressEvent: DEFAULT_CONFIG.X.suppressEvent, 
2328
 
                supercedes: DEFAULT_CONFIG.X.supercedes
2329
 
    
2330
 
            });
2331
 
 
2332
 
            /**
2333
 
            * The absolute y-coordinate position of the Overlay
2334
 
            * @config y
2335
 
            * @type Number
2336
 
            * @default null
2337
 
            */
2338
 
            cfg.addProperty(DEFAULT_CONFIG.Y.key, {
2339
 
 
2340
 
                handler: this.configY, 
2341
 
                validator: DEFAULT_CONFIG.Y.validator, 
2342
 
                suppressEvent: DEFAULT_CONFIG.Y.suppressEvent, 
2343
 
                supercedes: DEFAULT_CONFIG.Y.supercedes
2344
 
 
2345
 
            });
2346
 
 
2347
 
            /**
2348
 
            * An array with the absolute x and y positions of the Overlay
2349
 
            * @config xy
2350
 
            * @type Number[]
2351
 
            * @default null
2352
 
            */
2353
 
            cfg.addProperty(DEFAULT_CONFIG.XY.key, {
2354
 
                handler: this.configXY, 
2355
 
                suppressEvent: DEFAULT_CONFIG.XY.suppressEvent, 
2356
 
                supercedes: DEFAULT_CONFIG.XY.supercedes
2357
 
            });
2358
 
 
2359
 
            /**
2360
 
            * <p>
2361
 
            * The array of context arguments for context-sensitive positioning. 
2362
 
            * </p>
2363
 
            *
2364
 
            * <p>
2365
 
            * The format of the array is: <code>[contextElementOrId, overlayCorner, contextCorner, arrayOfTriggerEvents (optional)]</code>, the
2366
 
            * the 4 array elements described in detail below:
2367
 
            * </p>
2368
 
            *
2369
 
            * <dl>
2370
 
            * <dt>contextElementOrId &#60;String|HTMLElement&#62;</dt>
2371
 
            * <dd>A reference to the context element to which the overlay should be aligned (or it's id).</dd>
2372
 
            * <dt>overlayCorner &#60;String&#62;</dt>
2373
 
            * <dd>The corner of the overlay which is to be used for alignment. This corner will be aligned to the 
2374
 
            * corner of the context element defined by the "contextCorner" entry which follows. Supported string values are: 
2375
 
            * "tr" (top right), "tl" (top left), "br" (bottom right), or "bl" (bottom left).</dd>
2376
 
            * <dt>contextCorner &#60;String&#62;</dt>
2377
 
            * <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>
2378
 
            * <dt>arrayOfTriggerEvents (optional) &#60;Array[String|CustomEvent]&#62;</dt>
2379
 
            * <dd>
2380
 
            * <p>
2381
 
            * 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> 
2382
 
            * 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. 
2383
 
            * This is useful in situations where the layout of the document may change, resulting in the context element's position being modified.
2384
 
            * </p>
2385
 
            * <p>
2386
 
            * The array can contain either event type strings for events the instance publishes (e.g. "beforeShow") or CustomEvent instances. Additionally the following
2387
 
            * 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).
2388
 
            * </p>
2389
 
            * </dd>
2390
 
            * </dl>
2391
 
            *
2392
 
            * <p>
2393
 
            * For example, setting this property to <code>["img1", "tl", "bl"]</code> will 
2394
 
            * align the Overlay's top left corner to the bottom left corner of the
2395
 
            * context element with id "img1".
2396
 
            * </p>
2397
 
            * <p>
2398
 
            * Adding the optional trigger values: <code>["img1", "tl", "bl", ["beforeShow", "windowResize"]]</code>,
2399
 
            * will re-align the overlay position, whenever the "beforeShow" or "windowResize" events are fired.
2400
 
            * </p>
2401
 
            *
2402
 
            * @config context
2403
 
            * @type Array
2404
 
            * @default null
2405
 
            */
2406
 
            cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
2407
 
                handler: this.configContext, 
2408
 
                suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent, 
2409
 
                supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
2410
 
            });
2411
 
 
2412
 
            /**
2413
 
            * Determines whether or not the Overlay should be anchored 
2414
 
            * to the center of the viewport.
2415
 
            * 
2416
 
            * <p>This property can be set to:</p>
2417
 
            * 
2418
 
            * <dl>
2419
 
            * <dt>true</dt>
2420
 
            * <dd>
2421
 
            * To enable fixed center positioning
2422
 
            * <p>
2423
 
            * When enabled, the overlay will 
2424
 
            * be positioned in the center of viewport when initially displayed, and 
2425
 
            * will remain in the center of the viewport whenever the window is 
2426
 
            * scrolled or resized.
2427
 
            * </p>
2428
 
            * <p>
2429
 
            * If the overlay is too big for the viewport, 
2430
 
            * it's top left corner will be aligned with the top left corner of the viewport.
2431
 
            * </p>
2432
 
            * </dd>
2433
 
            * <dt>false</dt>
2434
 
            * <dd>
2435
 
            * To disable fixed center positioning.
2436
 
            * <p>In this case the overlay can still be 
2437
 
            * centered as a one-off operation, by invoking the <code>center()</code> method,
2438
 
            * however it will not remain centered when the window is scrolled/resized.
2439
 
            * </dd>
2440
 
            * <dt>"contained"<dt>
2441
 
            * <dd>To enable fixed center positioning, as with the <code>true</code> option.
2442
 
            * <p>However, unlike setting the property to <code>true</code>, 
2443
 
            * when the property is set to <code>"contained"</code>, if the overlay is 
2444
 
            * too big for the viewport, it will not get automatically centered when the 
2445
 
            * user scrolls or resizes the window (until the window is large enough to contain the 
2446
 
            * overlay). This is useful in cases where the Overlay has both header and footer 
2447
 
            * UI controls which the user may need to access.
2448
 
            * </p>
2449
 
            * </dd>
2450
 
            * </dl>
2451
 
            *
2452
 
            * @config fixedcenter
2453
 
            * @type Boolean | String
2454
 
            * @default false
2455
 
            */
2456
 
            cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
2457
 
                handler: this.configFixedCenter,
2458
 
                value: DEFAULT_CONFIG.FIXED_CENTER.value, 
2459
 
                validator: DEFAULT_CONFIG.FIXED_CENTER.validator, 
2460
 
                supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
2461
 
            });
2462
 
    
2463
 
            /**
2464
 
            * CSS width of the Overlay.
2465
 
            * @config width
2466
 
            * @type String
2467
 
            * @default null
2468
 
            */
2469
 
            cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
2470
 
                handler: this.configWidth, 
2471
 
                suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent, 
2472
 
                supercedes: DEFAULT_CONFIG.WIDTH.supercedes
2473
 
            });
2474
 
 
2475
 
            /**
2476
 
            * CSS height of the Overlay.
2477
 
            * @config height
2478
 
            * @type String
2479
 
            * @default null
2480
 
            */
2481
 
            cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
2482
 
                handler: this.configHeight, 
2483
 
                suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent, 
2484
 
                supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
2485
 
            });
2486
 
 
2487
 
            /**
2488
 
            * Standard module element which should auto fill out the height of the Overlay if the height config property is set.
2489
 
            * Supported values are "header", "body", "footer".
2490
 
            *
2491
 
            * @config autofillheight
2492
 
            * @type String
2493
 
            * @default null
2494
 
            */
2495
 
            cfg.addProperty(DEFAULT_CONFIG.AUTO_FILL_HEIGHT.key, {
2496
 
                handler: this.configAutoFillHeight, 
2497
 
                value : DEFAULT_CONFIG.AUTO_FILL_HEIGHT.value,
2498
 
                validator : this._validateAutoFill,
2499
 
                supercedes: DEFAULT_CONFIG.AUTO_FILL_HEIGHT.supercedes
2500
 
            });
2501
 
 
2502
 
            /**
2503
 
            * CSS z-index of the Overlay.
2504
 
            * @config zIndex
2505
 
            * @type Number
2506
 
            * @default null
2507
 
            */
2508
 
            cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
2509
 
                handler: this.configzIndex,
2510
 
                value: DEFAULT_CONFIG.ZINDEX.value
2511
 
            });
2512
 
 
2513
 
            /**
2514
 
            * True if the Overlay should be prevented from being positioned 
2515
 
            * out of the viewport.
2516
 
            * @config constraintoviewport
2517
 
            * @type Boolean
2518
 
            * @default false
2519
 
            */
2520
 
            cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
2521
 
 
2522
 
                handler: this.configConstrainToViewport, 
2523
 
                value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value, 
2524
 
                validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator, 
2525
 
                supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
2526
 
 
2527
 
            });
2528
 
 
2529
 
            /**
2530
 
            * @config iframe
2531
 
            * @description Boolean indicating whether or not the Overlay should 
2532
 
            * have an IFRAME shim; used to prevent SELECT elements from 
2533
 
            * poking through an Overlay instance in IE6.  When set to "true", 
2534
 
            * the iframe shim is created when the Overlay instance is intially
2535
 
            * made visible.
2536
 
            * @type Boolean
2537
 
            * @default true for IE6 and below, false for all other browsers.
2538
 
            */
2539
 
            cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
2540
 
 
2541
 
                handler: this.configIframe, 
2542
 
                value: DEFAULT_CONFIG.IFRAME.value, 
2543
 
                validator: DEFAULT_CONFIG.IFRAME.validator, 
2544
 
                supercedes: DEFAULT_CONFIG.IFRAME.supercedes
2545
 
 
2546
 
            });
2547
 
 
2548
 
            /**
2549
 
            * @config preventcontextoverlap
2550
 
            * @description Boolean indicating whether or not the Overlay should overlap its 
2551
 
            * context element (defined using the "context" configuration property) when the 
2552
 
            * "constraintoviewport" configuration property is set to "true".
2553
 
            * @type Boolean
2554
 
            * @default false
2555
 
            */
2556
 
            cfg.addProperty(DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.key, {
2557
 
 
2558
 
                value: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.value, 
2559
 
                validator: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.validator, 
2560
 
                supercedes: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.supercedes
2561
 
 
2562
 
            });
2563
 
 
2564
 
        },
2565
 
 
2566
 
        /**
2567
 
        * Moves the Overlay to the specified position. This function is  
2568
 
        * identical to calling this.cfg.setProperty("xy", [x,y]);
2569
 
        * @method moveTo
2570
 
        * @param {Number} x The Overlay's new x position
2571
 
        * @param {Number} y The Overlay's new y position
2572
 
        */
2573
 
        moveTo: function (x, y) {
2574
 
            this.cfg.setProperty("xy", [x, y]);
2575
 
        },
2576
 
 
2577
 
        /**
2578
 
        * Adds a CSS class ("hide-scrollbars") and removes a CSS class 
2579
 
        * ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2580
 
        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2581
 
        * @method hideMacGeckoScrollbars
2582
 
        */
2583
 
        hideMacGeckoScrollbars: function () {
2584
 
            Dom.replaceClass(this.element, "show-scrollbars", "hide-scrollbars");
2585
 
        },
2586
 
 
2587
 
        /**
2588
 
        * Adds a CSS class ("show-scrollbars") and removes a CSS class 
2589
 
        * ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X 
2590
 
        * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
2591
 
        * @method showMacGeckoScrollbars
2592
 
        */
2593
 
        showMacGeckoScrollbars: function () {
2594
 
            Dom.replaceClass(this.element, "hide-scrollbars", "show-scrollbars");
2595
 
        },
2596
 
 
2597
 
        /**
2598
 
         * Internal implementation to set the visibility of the overlay in the DOM.
2599
 
         *
2600
 
         * @method _setDomVisibility
2601
 
         * @param {boolean} visible Whether to show or hide the Overlay's outer element
2602
 
         * @protected
2603
 
         */
2604
 
        _setDomVisibility : function(show) {
2605
 
            Dom.setStyle(this.element, "visibility", (show) ? "visible" : "hidden");
2606
 
 
2607
 
            if (show) {
2608
 
                Dom.removeClass(this.element, "yui-overlay-hidden");
2609
 
            } else {
2610
 
                Dom.addClass(this.element, "yui-overlay-hidden");
2611
 
            }
2612
 
        },
2613
 
 
2614
 
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
2615
 
        /**
2616
 
        * The default event handler fired when the "visible" property is 
2617
 
        * changed.  This method is responsible for firing showEvent
2618
 
        * and hideEvent.
2619
 
        * @method configVisible
2620
 
        * @param {String} type The CustomEvent type (usually the property name)
2621
 
        * @param {Object[]} args The CustomEvent arguments. For configuration
2622
 
        * handlers, args[0] will equal the newly applied value for the property.
2623
 
        * @param {Object} obj The scope object. For configuration handlers, 
2624
 
        * this will usually equal the owner.
2625
 
        */
2626
 
        configVisible: function (type, args, obj) {
2627
 
 
2628
 
            var visible = args[0],
2629
 
                currentVis = Dom.getStyle(this.element, "visibility"),
2630
 
                effect = this.cfg.getProperty("effect"),
2631
 
                effectInstances = [],
2632
 
                isMacGecko = (this.platform == "mac" && UA.gecko),
2633
 
                alreadySubscribed = Config.alreadySubscribed,
2634
 
                eff, ei, e, i, j, k, h,
2635
 
                nEffects,
2636
 
                nEffectInstances;
2637
 
 
2638
 
            if (currentVis == "inherit") {
2639
 
                e = this.element.parentNode;
2640
 
 
2641
 
                while (e.nodeType != 9 && e.nodeType != 11) {
2642
 
                    currentVis = Dom.getStyle(e, "visibility");
2643
 
 
2644
 
                    if (currentVis != "inherit") {
2645
 
                        break;
2646
 
                    }
2647
 
 
2648
 
                    e = e.parentNode;
2649
 
                }
2650
 
 
2651
 
                if (currentVis == "inherit") {
2652
 
                    currentVis = "visible";
2653
 
                }
2654
 
            }
2655
 
 
2656
 
            if (effect) {
2657
 
                if (effect instanceof Array) {
2658
 
                    nEffects = effect.length;
2659
 
 
2660
 
                    for (i = 0; i < nEffects; i++) {
2661
 
                        eff = effect[i];
2662
 
                        effectInstances[effectInstances.length] = 
2663
 
                            eff.effect(this, eff.duration);
2664
 
 
2665
 
                    }
2666
 
                } else {
2667
 
                    effectInstances[effectInstances.length] = 
2668
 
                        effect.effect(this, effect.duration);
2669
 
                }
2670
 
            }
2671
 
 
2672
 
            if (visible) { // Show
2673
 
                if (isMacGecko) {
2674
 
                    this.showMacGeckoScrollbars();
2675
 
                }
2676
 
 
2677
 
                if (effect) { // Animate in
2678
 
                    if (visible) { // Animate in if not showing
2679
 
                        if (currentVis != "visible" || currentVis === "") {
2680
 
                            this.beforeShowEvent.fire();
2681
 
                            nEffectInstances = effectInstances.length;
2682
 
 
2683
 
                            for (j = 0; j < nEffectInstances; j++) {
2684
 
                                ei = effectInstances[j];
2685
 
                                if (j === 0 && !alreadySubscribed(
2686
 
                                        ei.animateInCompleteEvent, 
2687
 
                                        this.showEvent.fire, this.showEvent)) {
2688
 
 
2689
 
                                    /*
2690
 
                                         Delegate showEvent until end 
2691
 
                                         of animateInComplete
2692
 
                                    */
2693
 
 
2694
 
                                    ei.animateInCompleteEvent.subscribe(
2695
 
                                     this.showEvent.fire, this.showEvent, true);
2696
 
                                }
2697
 
                                ei.animateIn();
2698
 
                            }
2699
 
                        }
2700
 
                    }
2701
 
                } else { // Show
2702
 
                    if (currentVis != "visible" || currentVis === "") {
2703
 
                        this.beforeShowEvent.fire();
2704
 
 
2705
 
                        this._setDomVisibility(true);
2706
 
 
2707
 
                        this.cfg.refireEvent("iframe");
2708
 
                        this.showEvent.fire();
2709
 
                    } else {
2710
 
                        this._setDomVisibility(true);
2711
 
                    }
2712
 
                }
2713
 
            } else { // Hide
2714
 
 
2715
 
                if (isMacGecko) {
2716
 
                    this.hideMacGeckoScrollbars();
2717
 
                }
2718
 
 
2719
 
                if (effect) { // Animate out if showing
2720
 
                    if (currentVis == "visible") {
2721
 
                        this.beforeHideEvent.fire();
2722
 
 
2723
 
                        nEffectInstances = effectInstances.length;
2724
 
                        for (k = 0; k < nEffectInstances; k++) {
2725
 
                            h = effectInstances[k];
2726
 
    
2727
 
                            if (k === 0 && !alreadySubscribed(
2728
 
                                h.animateOutCompleteEvent, this.hideEvent.fire, 
2729
 
                                this.hideEvent)) {
2730
 
    
2731
 
                                /*
2732
 
                                     Delegate hideEvent until end 
2733
 
                                     of animateOutComplete
2734
 
                                */
2735
 
    
2736
 
                                h.animateOutCompleteEvent.subscribe(
2737
 
                                    this.hideEvent.fire, this.hideEvent, true);
2738
 
    
2739
 
                            }
2740
 
                            h.animateOut();
2741
 
                        }
2742
 
 
2743
 
                    } else if (currentVis === "") {
2744
 
                        this._setDomVisibility(false);
2745
 
                    }
2746
 
 
2747
 
                } else { // Simple hide
2748
 
 
2749
 
                    if (currentVis == "visible" || currentVis === "") {
2750
 
                        this.beforeHideEvent.fire();
2751
 
                        this._setDomVisibility(false);
2752
 
                        this.hideEvent.fire();
2753
 
                    } else {
2754
 
                        this._setDomVisibility(false);
2755
 
                    }
2756
 
                }
2757
 
            }
2758
 
        },
2759
 
 
2760
 
        /**
2761
 
        * Fixed center event handler used for centering on scroll/resize, but only if 
2762
 
        * the overlay is visible and, if "fixedcenter" is set to "contained", only if 
2763
 
        * the overlay fits within the viewport.
2764
 
        *
2765
 
        * @method doCenterOnDOMEvent
2766
 
        */
2767
 
        doCenterOnDOMEvent: function () {
2768
 
            var cfg = this.cfg,
2769
 
                fc = cfg.getProperty("fixedcenter");
2770
 
 
2771
 
            if (cfg.getProperty("visible")) {
2772
 
                if (fc && (fc !== _CONTAINED || this.fitsInViewport())) {
2773
 
                    this.center();
2774
 
                }
2775
 
            }
2776
 
        },
2777
 
 
2778
 
        /**
2779
 
         * Determines if the Overlay (including the offset value defined by Overlay.VIEWPORT_OFFSET) 
2780
 
         * will fit entirely inside the viewport, in both dimensions - width and height.
2781
 
         * 
2782
 
         * @method fitsInViewport
2783
 
         * @return boolean true if the Overlay will fit, false if not
2784
 
         */
2785
 
        fitsInViewport : function() {
2786
 
            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
2787
 
                element = this.element,
2788
 
                elementWidth = element.offsetWidth,
2789
 
                elementHeight = element.offsetHeight,
2790
 
                viewportWidth = Dom.getViewportWidth(),
2791
 
                viewportHeight = Dom.getViewportHeight();
2792
 
 
2793
 
            return ((elementWidth + nViewportOffset < viewportWidth) && (elementHeight + nViewportOffset < viewportHeight));
2794
 
        },
2795
 
 
2796
 
        /**
2797
 
        * The default event handler fired when the "fixedcenter" property 
2798
 
        * is changed.
2799
 
        * @method configFixedCenter
2800
 
        * @param {String} type The CustomEvent type (usually the property name)
2801
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2802
 
        * handlers, args[0] will equal the newly applied value for the property.
2803
 
        * @param {Object} obj The scope object. For configuration handlers, 
2804
 
        * this will usually equal the owner.
2805
 
        */
2806
 
        configFixedCenter: function (type, args, obj) {
2807
 
 
2808
 
            var val = args[0],
2809
 
                alreadySubscribed = Config.alreadySubscribed,
2810
 
                windowResizeEvent = Overlay.windowResizeEvent,
2811
 
                windowScrollEvent = Overlay.windowScrollEvent;
2812
 
 
2813
 
            if (val) {
2814
 
                this.center();
2815
 
 
2816
 
                if (!alreadySubscribed(this.beforeShowEvent, this.center)) {
2817
 
                    this.beforeShowEvent.subscribe(this.center);
2818
 
                }
2819
 
 
2820
 
                if (!alreadySubscribed(windowResizeEvent, this.doCenterOnDOMEvent, this)) {
2821
 
                    windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2822
 
                }
2823
 
 
2824
 
                if (!alreadySubscribed(windowScrollEvent, this.doCenterOnDOMEvent, this)) {
2825
 
                    windowScrollEvent.subscribe(this.doCenterOnDOMEvent, this, true);
2826
 
                }
2827
 
 
2828
 
            } else {
2829
 
                this.beforeShowEvent.unsubscribe(this.center);
2830
 
 
2831
 
                windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2832
 
                windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
2833
 
            }
2834
 
        },
2835
 
 
2836
 
        /**
2837
 
        * The default event handler fired when the "height" property is changed.
2838
 
        * @method configHeight
2839
 
        * @param {String} type The CustomEvent type (usually the property name)
2840
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2841
 
        * handlers, args[0] will equal the newly applied value for the property.
2842
 
        * @param {Object} obj The scope object. For configuration handlers, 
2843
 
        * this will usually equal the owner.
2844
 
        */
2845
 
        configHeight: function (type, args, obj) {
2846
 
 
2847
 
            var height = args[0],
2848
 
                el = this.element;
2849
 
 
2850
 
            Dom.setStyle(el, "height", height);
2851
 
            this.cfg.refireEvent("iframe");
2852
 
        },
2853
 
 
2854
 
        /**
2855
 
         * The default event handler fired when the "autofillheight" property is changed.
2856
 
         * @method configAutoFillHeight
2857
 
         *
2858
 
         * @param {String} type The CustomEvent type (usually the property name)
2859
 
         * @param {Object[]} args The CustomEvent arguments. For configuration 
2860
 
         * handlers, args[0] will equal the newly applied value for the property.
2861
 
         * @param {Object} obj The scope object. For configuration handlers, 
2862
 
         * this will usually equal the owner.
2863
 
         */
2864
 
        configAutoFillHeight: function (type, args, obj) {
2865
 
            var fillEl = args[0],
2866
 
                cfg = this.cfg,
2867
 
                autoFillHeight = "autofillheight",
2868
 
                height = "height",
2869
 
                currEl = cfg.getProperty(autoFillHeight),
2870
 
                autoFill = this._autoFillOnHeightChange;
2871
 
 
2872
 
            cfg.unsubscribeFromConfigEvent(height, autoFill);
2873
 
            Module.textResizeEvent.unsubscribe(autoFill);
2874
 
            this.changeContentEvent.unsubscribe(autoFill);
2875
 
 
2876
 
            if (currEl && fillEl !== currEl && this[currEl]) {
2877
 
                Dom.setStyle(this[currEl], height, "");
2878
 
            }
2879
 
 
2880
 
            if (fillEl) {
2881
 
                fillEl = Lang.trim(fillEl.toLowerCase());
2882
 
 
2883
 
                cfg.subscribeToConfigEvent(height, autoFill, this[fillEl], this);
2884
 
                Module.textResizeEvent.subscribe(autoFill, this[fillEl], this);
2885
 
                this.changeContentEvent.subscribe(autoFill, this[fillEl], this);
2886
 
 
2887
 
                cfg.setProperty(autoFillHeight, fillEl, true);
2888
 
            }
2889
 
        },
2890
 
 
2891
 
        /**
2892
 
        * The default event handler fired when the "width" property is changed.
2893
 
        * @method configWidth
2894
 
        * @param {String} type The CustomEvent type (usually the property name)
2895
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2896
 
        * handlers, args[0] will equal the newly applied value for the property.
2897
 
        * @param {Object} obj The scope object. For configuration handlers, 
2898
 
        * this will usually equal the owner.
2899
 
        */
2900
 
        configWidth: function (type, args, obj) {
2901
 
 
2902
 
            var width = args[0],
2903
 
                el = this.element;
2904
 
 
2905
 
            Dom.setStyle(el, "width", width);
2906
 
            this.cfg.refireEvent("iframe");
2907
 
        },
2908
 
 
2909
 
        /**
2910
 
        * The default event handler fired when the "zIndex" property is changed.
2911
 
        * @method configzIndex
2912
 
        * @param {String} type The CustomEvent type (usually the property name)
2913
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2914
 
        * handlers, args[0] will equal the newly applied value for the property.
2915
 
        * @param {Object} obj The scope object. For configuration handlers, 
2916
 
        * this will usually equal the owner.
2917
 
        */
2918
 
        configzIndex: function (type, args, obj) {
2919
 
 
2920
 
            var zIndex = args[0],
2921
 
                el = this.element;
2922
 
 
2923
 
            if (! zIndex) {
2924
 
                zIndex = Dom.getStyle(el, "zIndex");
2925
 
                if (! zIndex || isNaN(zIndex)) {
2926
 
                    zIndex = 0;
2927
 
                }
2928
 
            }
2929
 
 
2930
 
            if (this.iframe || this.cfg.getProperty("iframe") === true) {
2931
 
                if (zIndex <= 0) {
2932
 
                    zIndex = 1;
2933
 
                }
2934
 
            }
2935
 
 
2936
 
            Dom.setStyle(el, "zIndex", zIndex);
2937
 
            this.cfg.setProperty("zIndex", zIndex, true);
2938
 
 
2939
 
            if (this.iframe) {
2940
 
                this.stackIframe();
2941
 
            }
2942
 
        },
2943
 
 
2944
 
        /**
2945
 
        * The default event handler fired when the "xy" property is changed.
2946
 
        * @method configXY
2947
 
        * @param {String} type The CustomEvent type (usually the property name)
2948
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2949
 
        * handlers, args[0] will equal the newly applied value for the property.
2950
 
        * @param {Object} obj The scope object. For configuration handlers, 
2951
 
        * this will usually equal the owner.
2952
 
        */
2953
 
        configXY: function (type, args, obj) {
2954
 
 
2955
 
            var pos = args[0],
2956
 
                x = pos[0],
2957
 
                y = pos[1];
2958
 
 
2959
 
            this.cfg.setProperty("x", x);
2960
 
            this.cfg.setProperty("y", y);
2961
 
 
2962
 
            this.beforeMoveEvent.fire([x, y]);
2963
 
 
2964
 
            x = this.cfg.getProperty("x");
2965
 
            y = this.cfg.getProperty("y");
2966
 
 
2967
 
            YAHOO.log(("xy: " + [x, y]), "iframe");
2968
 
 
2969
 
            this.cfg.refireEvent("iframe");
2970
 
            this.moveEvent.fire([x, y]);
2971
 
        },
2972
 
 
2973
 
        /**
2974
 
        * The default event handler fired when the "x" property is changed.
2975
 
        * @method configX
2976
 
        * @param {String} type The CustomEvent type (usually the property name)
2977
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
2978
 
        * handlers, args[0] will equal the newly applied value for the property.
2979
 
        * @param {Object} obj The scope object. For configuration handlers, 
2980
 
        * this will usually equal the owner.
2981
 
        */
2982
 
        configX: function (type, args, obj) {
2983
 
 
2984
 
            var x = args[0],
2985
 
                y = this.cfg.getProperty("y");
2986
 
 
2987
 
            this.cfg.setProperty("x", x, true);
2988
 
            this.cfg.setProperty("y", y, true);
2989
 
 
2990
 
            this.beforeMoveEvent.fire([x, y]);
2991
 
 
2992
 
            x = this.cfg.getProperty("x");
2993
 
            y = this.cfg.getProperty("y");
2994
 
            
2995
 
            Dom.setX(this.element, x, true);
2996
 
 
2997
 
            this.cfg.setProperty("xy", [x, y], true);
2998
 
 
2999
 
            this.cfg.refireEvent("iframe");
3000
 
            this.moveEvent.fire([x, y]);
3001
 
        },
3002
 
 
3003
 
        /**
3004
 
        * The default event handler fired when the "y" property is changed.
3005
 
        * @method configY
3006
 
        * @param {String} type The CustomEvent type (usually the property name)
3007
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3008
 
        * handlers, args[0] will equal the newly applied value for the property.
3009
 
        * @param {Object} obj The scope object. For configuration handlers, 
3010
 
        * this will usually equal the owner.
3011
 
        */
3012
 
        configY: function (type, args, obj) {
3013
 
 
3014
 
            var x = this.cfg.getProperty("x"),
3015
 
                y = args[0];
3016
 
 
3017
 
            this.cfg.setProperty("x", x, true);
3018
 
            this.cfg.setProperty("y", y, true);
3019
 
 
3020
 
            this.beforeMoveEvent.fire([x, y]);
3021
 
 
3022
 
            x = this.cfg.getProperty("x");
3023
 
            y = this.cfg.getProperty("y");
3024
 
 
3025
 
            Dom.setY(this.element, y, true);
3026
 
 
3027
 
            this.cfg.setProperty("xy", [x, y], true);
3028
 
 
3029
 
            this.cfg.refireEvent("iframe");
3030
 
            this.moveEvent.fire([x, y]);
3031
 
        },
3032
 
        
3033
 
        /**
3034
 
        * Shows the iframe shim, if it has been enabled.
3035
 
        * @method showIframe
3036
 
        */
3037
 
        showIframe: function () {
3038
 
 
3039
 
            var oIFrame = this.iframe,
3040
 
                oParentNode;
3041
 
 
3042
 
            if (oIFrame) {
3043
 
                oParentNode = this.element.parentNode;
3044
 
 
3045
 
                if (oParentNode != oIFrame.parentNode) {
3046
 
                    this._addToParent(oParentNode, oIFrame);
3047
 
                }
3048
 
                oIFrame.style.display = "block";
3049
 
            }
3050
 
        },
3051
 
 
3052
 
        /**
3053
 
        * Hides the iframe shim, if it has been enabled.
3054
 
        * @method hideIframe
3055
 
        */
3056
 
        hideIframe: function () {
3057
 
            if (this.iframe) {
3058
 
                this.iframe.style.display = "none";
3059
 
            }
3060
 
        },
3061
 
 
3062
 
        /**
3063
 
        * Syncronizes the size and position of iframe shim to that of its 
3064
 
        * corresponding Overlay instance.
3065
 
        * @method syncIframe
3066
 
        */
3067
 
        syncIframe: function () {
3068
 
 
3069
 
            var oIFrame = this.iframe,
3070
 
                oElement = this.element,
3071
 
                nOffset = Overlay.IFRAME_OFFSET,
3072
 
                nDimensionOffset = (nOffset * 2),
3073
 
                aXY;
3074
 
 
3075
 
            if (oIFrame) {
3076
 
                // Size <iframe>
3077
 
                oIFrame.style.width = (oElement.offsetWidth + nDimensionOffset + "px");
3078
 
                oIFrame.style.height = (oElement.offsetHeight + nDimensionOffset + "px");
3079
 
 
3080
 
                // Position <iframe>
3081
 
                aXY = this.cfg.getProperty("xy");
3082
 
 
3083
 
                if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
3084
 
                    this.syncPosition();
3085
 
                    aXY = this.cfg.getProperty("xy");
3086
 
                }
3087
 
                Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
3088
 
            }
3089
 
        },
3090
 
 
3091
 
        /**
3092
 
         * Sets the zindex of the iframe shim, if it exists, based on the zindex of
3093
 
         * the Overlay element. The zindex of the iframe is set to be one less 
3094
 
         * than the Overlay element's zindex.
3095
 
         * 
3096
 
         * <p>NOTE: This method will not bump up the zindex of the Overlay element
3097
 
         * to ensure that the iframe shim has a non-negative zindex.
3098
 
         * If you require the iframe zindex to be 0 or higher, the zindex of 
3099
 
         * the Overlay element should be set to a value greater than 0, before 
3100
 
         * this method is called.
3101
 
         * </p>
3102
 
         * @method stackIframe
3103
 
         */
3104
 
        stackIframe: function () {
3105
 
            if (this.iframe) {
3106
 
                var overlayZ = Dom.getStyle(this.element, "zIndex");
3107
 
                if (!YAHOO.lang.isUndefined(overlayZ) && !isNaN(overlayZ)) {
3108
 
                    Dom.setStyle(this.iframe, "zIndex", (overlayZ - 1));
3109
 
                }
3110
 
            }
3111
 
        },
3112
 
 
3113
 
        /**
3114
 
        * The default event handler fired when the "iframe" property is changed.
3115
 
        * @method configIframe
3116
 
        * @param {String} type The CustomEvent type (usually the property name)
3117
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3118
 
        * handlers, args[0] will equal the newly applied value for the property.
3119
 
        * @param {Object} obj The scope object. For configuration handlers, 
3120
 
        * this will usually equal the owner.
3121
 
        */
3122
 
        configIframe: function (type, args, obj) {
3123
 
 
3124
 
            var bIFrame = args[0];
3125
 
 
3126
 
            function createIFrame() {
3127
 
 
3128
 
                var oIFrame = this.iframe,
3129
 
                    oElement = this.element,
3130
 
                    oParent;
3131
 
 
3132
 
                if (!oIFrame) {
3133
 
                    if (!m_oIFrameTemplate) {
3134
 
                        m_oIFrameTemplate = document.createElement("iframe");
3135
 
 
3136
 
                        if (this.isSecure) {
3137
 
                            m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
3138
 
                        }
3139
 
 
3140
 
                        /*
3141
 
                            Set the opacity of the <iframe> to 0 so that it 
3142
 
                            doesn't modify the opacity of any transparent 
3143
 
                            elements that may be on top of it (like a shadow).
3144
 
                        */
3145
 
                        if (UA.ie) {
3146
 
                            m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
3147
 
                            /*
3148
 
                                 Need to set the "frameBorder" property to 0 
3149
 
                                 supress the default <iframe> border in IE.  
3150
 
                                 Setting the CSS "border" property alone 
3151
 
                                 doesn't supress it.
3152
 
                            */
3153
 
                            m_oIFrameTemplate.frameBorder = 0;
3154
 
                        }
3155
 
                        else {
3156
 
                            m_oIFrameTemplate.style.opacity = "0";
3157
 
                        }
3158
 
 
3159
 
                        m_oIFrameTemplate.style.position = "absolute";
3160
 
                        m_oIFrameTemplate.style.border = "none";
3161
 
                        m_oIFrameTemplate.style.margin = "0";
3162
 
                        m_oIFrameTemplate.style.padding = "0";
3163
 
                        m_oIFrameTemplate.style.display = "none";
3164
 
                        m_oIFrameTemplate.tabIndex = -1;
3165
 
                    }
3166
 
 
3167
 
                    oIFrame = m_oIFrameTemplate.cloneNode(false);
3168
 
                    oParent = oElement.parentNode;
3169
 
 
3170
 
                    var parentNode = oParent || document.body;
3171
 
 
3172
 
                    this._addToParent(parentNode, oIFrame);
3173
 
                    this.iframe = oIFrame;
3174
 
                }
3175
 
 
3176
 
                /*
3177
 
                     Show the <iframe> before positioning it since the "setXY" 
3178
 
                     method of DOM requires the element be in the document 
3179
 
                     and visible.
3180
 
                */
3181
 
                this.showIframe();
3182
 
 
3183
 
                /*
3184
 
                     Syncronize the size and position of the <iframe> to that 
3185
 
                     of the Overlay.
3186
 
                */
3187
 
                this.syncIframe();
3188
 
                this.stackIframe();
3189
 
 
3190
 
                // Add event listeners to update the <iframe> when necessary
3191
 
                if (!this._hasIframeEventListeners) {
3192
 
                    this.showEvent.subscribe(this.showIframe);
3193
 
                    this.hideEvent.subscribe(this.hideIframe);
3194
 
                    this.changeContentEvent.subscribe(this.syncIframe);
3195
 
 
3196
 
                    this._hasIframeEventListeners = true;
3197
 
                }
3198
 
            }
3199
 
 
3200
 
            function onBeforeShow() {
3201
 
                createIFrame.call(this);
3202
 
                this.beforeShowEvent.unsubscribe(onBeforeShow);
3203
 
                this._iframeDeferred = false;
3204
 
            }
3205
 
 
3206
 
            if (bIFrame) { // <iframe> shim is enabled
3207
 
 
3208
 
                if (this.cfg.getProperty("visible")) {
3209
 
                    createIFrame.call(this);
3210
 
                } else {
3211
 
                    if (!this._iframeDeferred) {
3212
 
                        this.beforeShowEvent.subscribe(onBeforeShow);
3213
 
                        this._iframeDeferred = true;
3214
 
                    }
3215
 
                }
3216
 
 
3217
 
            } else {    // <iframe> shim is disabled
3218
 
                this.hideIframe();
3219
 
 
3220
 
                if (this._hasIframeEventListeners) {
3221
 
                    this.showEvent.unsubscribe(this.showIframe);
3222
 
                    this.hideEvent.unsubscribe(this.hideIframe);
3223
 
                    this.changeContentEvent.unsubscribe(this.syncIframe);
3224
 
 
3225
 
                    this._hasIframeEventListeners = false;
3226
 
                }
3227
 
            }
3228
 
        },
3229
 
 
3230
 
        /**
3231
 
         * Set's the container's XY value from DOM if not already set.
3232
 
         * 
3233
 
         * Differs from syncPosition, in that the XY value is only sync'd with DOM if 
3234
 
         * not already set. The method also refire's the XY config property event, so any
3235
 
         * beforeMove, Move event listeners are invoked.
3236
 
         * 
3237
 
         * @method _primeXYFromDOM
3238
 
         * @protected
3239
 
         */
3240
 
        _primeXYFromDOM : function() {
3241
 
            if (YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))) {
3242
 
                // Set CFG XY based on DOM XY
3243
 
                this.syncPosition();
3244
 
                // Account for XY being set silently in syncPosition (no moveTo fired/called)
3245
 
                this.cfg.refireEvent("xy");
3246
 
                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3247
 
            }
3248
 
        },
3249
 
 
3250
 
        /**
3251
 
        * The default event handler fired when the "constraintoviewport" 
3252
 
        * property is changed.
3253
 
        * @method configConstrainToViewport
3254
 
        * @param {String} type The CustomEvent type (usually the property name)
3255
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3256
 
        * handlers, args[0] will equal the newly applied value for 
3257
 
        * the property.
3258
 
        * @param {Object} obj The scope object. For configuration handlers, 
3259
 
        * this will usually equal the owner.
3260
 
        */
3261
 
        configConstrainToViewport: function (type, args, obj) {
3262
 
            var val = args[0];
3263
 
 
3264
 
            if (val) {
3265
 
                if (! Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
3266
 
                    this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
3267
 
                }
3268
 
                if (! Config.alreadySubscribed(this.beforeShowEvent, this._primeXYFromDOM)) {
3269
 
                    this.beforeShowEvent.subscribe(this._primeXYFromDOM);
3270
 
                }
3271
 
            } else {
3272
 
                this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
3273
 
                this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
3274
 
            }
3275
 
        },
3276
 
 
3277
 
         /**
3278
 
        * The default event handler fired when the "context" property
3279
 
        * is changed.
3280
 
        * 
3281
 
        * @method configContext
3282
 
        * @param {String} type The CustomEvent type (usually the property name)
3283
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3284
 
        * handlers, args[0] will equal the newly applied value for the property.
3285
 
        * @param {Object} obj The scope object. For configuration handlers, 
3286
 
        * this will usually equal the owner.
3287
 
        */
3288
 
        configContext: function (type, args, obj) {
3289
 
 
3290
 
            var contextArgs = args[0],
3291
 
                contextEl,
3292
 
                elementMagnetCorner,
3293
 
                contextMagnetCorner,
3294
 
                triggers,
3295
 
                defTriggers = this.CONTEXT_TRIGGERS;
3296
 
 
3297
 
            if (contextArgs) {
3298
 
 
3299
 
                contextEl = contextArgs[0];
3300
 
                elementMagnetCorner = contextArgs[1];
3301
 
                contextMagnetCorner = contextArgs[2];
3302
 
                triggers = contextArgs[3];
3303
 
 
3304
 
                if (defTriggers && defTriggers.length > 0) {
3305
 
                    triggers = (triggers || []).concat(defTriggers);
3306
 
                }
3307
 
 
3308
 
                if (contextEl) {
3309
 
                    if (typeof contextEl == "string") {
3310
 
                        this.cfg.setProperty("context", [
3311
 
                                document.getElementById(contextEl), 
3312
 
                                elementMagnetCorner,
3313
 
                                contextMagnetCorner,
3314
 
                                triggers ],
3315
 
                                true);
3316
 
                    }
3317
 
 
3318
 
                    if (elementMagnetCorner && contextMagnetCorner) {
3319
 
                        this.align(elementMagnetCorner, contextMagnetCorner);
3320
 
                    }
3321
 
 
3322
 
                    if (this._contextTriggers) {
3323
 
                        // Unsubscribe Old Set
3324
 
                        this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
3325
 
                    }
3326
 
 
3327
 
                    if (triggers) {
3328
 
                        // Subscribe New Set
3329
 
                        this._processTriggers(triggers, _SUBSCRIBE, this._alignOnTrigger);
3330
 
                        this._contextTriggers = triggers;
3331
 
                    }
3332
 
                }
3333
 
            }
3334
 
        },
3335
 
 
3336
 
        /**
3337
 
         * Custom Event handler for context alignment triggers. Invokes the align method
3338
 
         * 
3339
 
         * @method _alignOnTrigger
3340
 
         * @protected
3341
 
         * 
3342
 
         * @param {String} type The event type (not used by the default implementation)
3343
 
         * @param {Any[]} args The array of arguments for the trigger event (not used by the default implementation)
3344
 
         */
3345
 
        _alignOnTrigger: function(type, args) {
3346
 
            this.align();
3347
 
        },
3348
 
 
3349
 
        /**
3350
 
         * Helper method to locate the custom event instance for the event name string
3351
 
         * passed in. As a convenience measure, any custom events passed in are returned.
3352
 
         *
3353
 
         * @method _findTriggerCE
3354
 
         * @private
3355
 
         *
3356
 
         * @param {String|CustomEvent} t Either a CustomEvent, or event type (e.g. "windowScroll") for which a 
3357
 
         * custom event instance needs to be looked up from the Overlay._TRIGGER_MAP.
3358
 
         */
3359
 
        _findTriggerCE : function(t) {
3360
 
            var tce = null;
3361
 
            if (t instanceof CustomEvent) {
3362
 
                tce = t;
3363
 
            } else if (Overlay._TRIGGER_MAP[t]) {
3364
 
                tce = Overlay._TRIGGER_MAP[t];
3365
 
            }
3366
 
            return tce;
3367
 
        },
3368
 
 
3369
 
        /**
3370
 
         * Utility method that subscribes or unsubscribes the given 
3371
 
         * function from the list of trigger events provided.
3372
 
         *
3373
 
         * @method _processTriggers
3374
 
         * @protected 
3375
 
         *
3376
 
         * @param {Array[String|CustomEvent]} triggers An array of either CustomEvents, event type strings 
3377
 
         * (e.g. "beforeShow", "windowScroll") to/from which the provided function should be 
3378
 
         * subscribed/unsubscribed respectively.
3379
 
         *
3380
 
         * @param {String} mode Either "subscribe" or "unsubscribe", specifying whether or not
3381
 
         * we are subscribing or unsubscribing trigger listeners
3382
 
         * 
3383
 
         * @param {Function} fn The function to be subscribed/unsubscribed to/from the trigger event.
3384
 
         * Context is always set to the overlay instance, and no additional object argument 
3385
 
         * get passed to the subscribed function.
3386
 
         */
3387
 
        _processTriggers : function(triggers, mode, fn) {
3388
 
            var t, tce;
3389
 
 
3390
 
            for (var i = 0, l = triggers.length; i < l; ++i) {
3391
 
                t = triggers[i];
3392
 
                tce = this._findTriggerCE(t);
3393
 
                if (tce) {
3394
 
                    tce[mode](fn, this, true);
3395
 
                } else {
3396
 
                    this[mode](t, fn);
3397
 
                }
3398
 
            }
3399
 
        },
3400
 
 
3401
 
        // END BUILT-IN PROPERTY EVENT HANDLERS //
3402
 
        /**
3403
 
        * Aligns the Overlay to its context element using the specified corner 
3404
 
        * points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, 
3405
 
        * and BOTTOM_RIGHT.
3406
 
        * @method align
3407
 
        * @param {String} elementAlign  The String representing the corner of 
3408
 
        * the Overlay that should be aligned to the context element
3409
 
        * @param {String} contextAlign  The corner of the context element 
3410
 
        * that the elementAlign corner should stick to.
3411
 
        */
3412
 
        align: function (elementAlign, contextAlign) {
3413
 
 
3414
 
            var contextArgs = this.cfg.getProperty("context"),
3415
 
                me = this,
3416
 
                context,
3417
 
                element,
3418
 
                contextRegion;
3419
 
 
3420
 
            function doAlign(v, h) {
3421
 
    
3422
 
                switch (elementAlign) {
3423
 
    
3424
 
                case Overlay.TOP_LEFT:
3425
 
                    me.moveTo(h, v);
3426
 
                    break;
3427
 
    
3428
 
                case Overlay.TOP_RIGHT:
3429
 
                    me.moveTo((h - element.offsetWidth), v);
3430
 
                    break;
3431
 
    
3432
 
                case Overlay.BOTTOM_LEFT:
3433
 
                    me.moveTo(h, (v - element.offsetHeight));
3434
 
                    break;
3435
 
    
3436
 
                case Overlay.BOTTOM_RIGHT:
3437
 
                    me.moveTo((h - element.offsetWidth), 
3438
 
                        (v - element.offsetHeight));
3439
 
                    break;
3440
 
                }
3441
 
            }
3442
 
    
3443
 
    
3444
 
            if (contextArgs) {
3445
 
            
3446
 
                context = contextArgs[0];
3447
 
                element = this.element;
3448
 
                me = this;
3449
 
                
3450
 
                if (! elementAlign) {
3451
 
                    elementAlign = contextArgs[1];
3452
 
                }
3453
 
                
3454
 
                if (! contextAlign) {
3455
 
                    contextAlign = contextArgs[2];
3456
 
                }
3457
 
                
3458
 
                if (element && context) {
3459
 
                    contextRegion = Dom.getRegion(context);
3460
 
 
3461
 
                    switch (contextAlign) {
3462
 
    
3463
 
                    case Overlay.TOP_LEFT:
3464
 
                        doAlign(contextRegion.top, contextRegion.left);
3465
 
                        break;
3466
 
    
3467
 
                    case Overlay.TOP_RIGHT:
3468
 
                        doAlign(contextRegion.top, contextRegion.right);
3469
 
                        break;
3470
 
    
3471
 
                    case Overlay.BOTTOM_LEFT:
3472
 
                        doAlign(contextRegion.bottom, contextRegion.left);
3473
 
                        break;
3474
 
    
3475
 
                    case Overlay.BOTTOM_RIGHT:
3476
 
                        doAlign(contextRegion.bottom, contextRegion.right);
3477
 
                        break;
3478
 
                    }
3479
 
    
3480
 
                }
3481
 
    
3482
 
            }
3483
 
            
3484
 
        },
3485
 
 
3486
 
        /**
3487
 
        * The default event handler executed when the moveEvent is fired, if the 
3488
 
        * "constraintoviewport" is set to true.
3489
 
        * @method enforceConstraints
3490
 
        * @param {String} type The CustomEvent type (usually the property name)
3491
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
3492
 
        * handlers, args[0] will equal the newly applied value for the property.
3493
 
        * @param {Object} obj The scope object. For configuration handlers, 
3494
 
        * this will usually equal the owner.
3495
 
        */
3496
 
        enforceConstraints: function (type, args, obj) {
3497
 
            var pos = args[0];
3498
 
            
3499
 
            var cXY = this.getConstrainedXY(pos[0], pos[1]);
3500
 
            this.cfg.setProperty("x", cXY[0], true);
3501
 
            this.cfg.setProperty("y", cXY[1], true);
3502
 
            this.cfg.setProperty("xy", cXY, true);
3503
 
        },
3504
 
 
3505
 
 
3506
 
        /**
3507
 
         * Given x coordinate value, returns the calculated x coordinate required to 
3508
 
         * position the Overlay if it is to be constrained to the viewport, based on the 
3509
 
         * current element size, viewport dimensions and scroll values.
3510
 
         *
3511
 
         * @param {Number} x The X coordinate value to be constrained
3512
 
         * @return {Number} The constrained x coordinate
3513
 
         */             
3514
 
        getConstrainedX: function (x) {
3515
 
 
3516
 
            var oOverlay = this,
3517
 
                oOverlayEl = oOverlay.element,
3518
 
                nOverlayOffsetWidth = oOverlayEl.offsetWidth,
3519
 
 
3520
 
                nViewportOffset = Overlay.VIEWPORT_OFFSET,
3521
 
                viewPortWidth = Dom.getViewportWidth(),
3522
 
                scrollX = Dom.getDocumentScrollLeft(),
3523
 
 
3524
 
                bCanConstrain = (nOverlayOffsetWidth + nViewportOffset < viewPortWidth),
3525
 
 
3526
 
                aContext = this.cfg.getProperty("context"),
3527
 
                oContextEl,
3528
 
                nContextElX,
3529
 
                nContextElWidth,
3530
 
 
3531
 
                bFlipped = false,
3532
 
 
3533
 
                nLeftRegionWidth,
3534
 
                nRightRegionWidth,
3535
 
 
3536
 
                leftConstraint = scrollX + nViewportOffset,
3537
 
                rightConstraint = scrollX + viewPortWidth - nOverlayOffsetWidth - nViewportOffset,
3538
 
 
3539
 
                xNew = x,
3540
 
 
3541
 
                oOverlapPositions = {
3542
 
 
3543
 
                    "tltr": true,
3544
 
                    "blbr": true,
3545
 
                    "brbl": true,
3546
 
                    "trtl": true
3547
 
                
3548
 
                };
3549
 
 
3550
 
 
3551
 
            var flipHorizontal = function () {
3552
 
            
3553
 
                var nNewX;
3554
 
            
3555
 
                if ((oOverlay.cfg.getProperty("x") - scrollX) > nContextElX) {
3556
 
                    nNewX = (nContextElX - nOverlayOffsetWidth);
3557
 
                }
3558
 
                else {
3559
 
                    nNewX = (nContextElX + nContextElWidth);
3560
 
                }
3561
 
                
3562
 
    
3563
 
                oOverlay.cfg.setProperty("x", (nNewX + scrollX), true);
3564
 
    
3565
 
                return nNewX;
3566
 
    
3567
 
            };
3568
 
 
3569
 
 
3570
 
 
3571
 
            /*
3572
 
                 Uses the context element's position to calculate the availble width 
3573
 
                 to the right and left of it to display its corresponding Overlay.
3574
 
            */
3575
 
 
3576
 
            var getDisplayRegionWidth = function () {
3577
 
 
3578
 
                // The Overlay is to the right of the context element
3579
 
 
3580
 
                if ((oOverlay.cfg.getProperty("x") - scrollX) > nContextElX) {
3581
 
                    return (nRightRegionWidth - nViewportOffset);
3582
 
                }
3583
 
                else {  // The Overlay is to the left of the context element
3584
 
                    return (nLeftRegionWidth - nViewportOffset);
3585
 
                }
3586
 
            
3587
 
            };
3588
 
    
3589
 
 
3590
 
            /*
3591
 
                Positions the Overlay to the left or right of the context element so that it remains 
3592
 
                inside the viewport.
3593
 
            */
3594
 
    
3595
 
            var setHorizontalPosition = function () {
3596
 
            
3597
 
                var nDisplayRegionWidth = getDisplayRegionWidth(),
3598
 
                    fnReturnVal;
3599
 
 
3600
 
                if (nOverlayOffsetWidth > nDisplayRegionWidth) {
3601
 
        
3602
 
                    if (bFlipped) {
3603
 
        
3604
 
                        /*
3605
 
                             All possible positions and values have been 
3606
 
                             tried, but none were successful, so fall back 
3607
 
                             to the original size and position.
3608
 
                        */
3609
 
    
3610
 
                        flipHorizontal();
3611
 
                        
3612
 
                    }
3613
 
                    else {
3614
 
        
3615
 
                        flipHorizontal();
3616
 
 
3617
 
                        bFlipped = true;
3618
 
        
3619
 
                        fnReturnVal = setHorizontalPosition();
3620
 
        
3621
 
                    }
3622
 
                
3623
 
                }
3624
 
        
3625
 
                return fnReturnVal;
3626
 
            
3627
 
            };
3628
 
 
3629
 
            // Determine if the current value for the Overlay's "x" configuration property will
3630
 
            // result in the Overlay being positioned outside the boundaries of the viewport
3631
 
            
3632
 
            if (x < leftConstraint || x > rightConstraint) {
3633
 
 
3634
 
                // The current value for the Overlay's "x" configuration property WILL
3635
 
                // result in the Overlay being positioned outside the boundaries of the viewport
3636
 
 
3637
 
                if (bCanConstrain) {
3638
 
 
3639
 
                    //  If the "preventcontextoverlap" configuration property is set to "true", 
3640
 
                    //  try to flip the Overlay to both keep it inside the boundaries of the 
3641
 
                    //  viewport AND from overlaping its context element.
3642
 
    
3643
 
                    if (this.cfg.getProperty("preventcontextoverlap") && aContext && 
3644
 
                        oOverlapPositions[(aContext[1] + aContext[2])]) {
3645
 
        
3646
 
                        oContextEl = aContext[0];
3647
 
                        nContextElX = Dom.getX(oContextEl) - scrollX;
3648
 
                        nContextElWidth = oContextEl.offsetWidth;
3649
 
                        nLeftRegionWidth = nContextElX;
3650
 
                        nRightRegionWidth = (viewPortWidth - (nContextElX + nContextElWidth));
3651
 
        
3652
 
                        setHorizontalPosition();
3653
 
                        
3654
 
                        xNew = this.cfg.getProperty("x");
3655
 
                    
3656
 
                    }
3657
 
                    else {
3658
 
 
3659
 
                        if (x < leftConstraint) {
3660
 
                            xNew = leftConstraint;
3661
 
                        } else if (x > rightConstraint) {
3662
 
                            xNew = rightConstraint;
3663
 
                        }
3664
 
 
3665
 
                    }
3666
 
 
3667
 
                } else {
3668
 
                    //  The "x" configuration property cannot be set to a value that will keep
3669
 
                    //  entire Overlay inside the boundary of the viewport.  Therefore, set  
3670
 
                    //  the "x" configuration property to scrollY to keep as much of the 
3671
 
                    //  Overlay inside the viewport as possible.                
3672
 
                    xNew = nViewportOffset + scrollX;
3673
 
                }
3674
 
 
3675
 
            }
3676
 
 
3677
 
            return xNew;
3678
 
        
3679
 
        },
3680
 
 
3681
 
 
3682
 
        /**
3683
 
         * Given y coordinate value, returns the calculated y coordinate required to 
3684
 
         * position the Overlay if it is to be constrained to the viewport, based on the 
3685
 
         * current element size, viewport dimensions and scroll values.
3686
 
         *
3687
 
         * @param {Number} y The Y coordinate value to be constrained
3688
 
         * @return {Number} The constrained y coordinate
3689
 
         */             
3690
 
        getConstrainedY: function (y) {
3691
 
 
3692
 
            var oOverlay = this,
3693
 
                oOverlayEl = oOverlay.element,
3694
 
                nOverlayOffsetHeight = oOverlayEl.offsetHeight,
3695
 
            
3696
 
                nViewportOffset = Overlay.VIEWPORT_OFFSET,
3697
 
                viewPortHeight = Dom.getViewportHeight(),
3698
 
                scrollY = Dom.getDocumentScrollTop(),
3699
 
 
3700
 
                bCanConstrain = (nOverlayOffsetHeight + nViewportOffset < viewPortHeight),
3701
 
 
3702
 
                aContext = this.cfg.getProperty("context"),
3703
 
                oContextEl,
3704
 
                nContextElY,
3705
 
                nContextElHeight,
3706
 
 
3707
 
                bFlipped = false,
3708
 
 
3709
 
                nTopRegionHeight,
3710
 
                nBottomRegionHeight,
3711
 
 
3712
 
                topConstraint = scrollY + nViewportOffset,
3713
 
                bottomConstraint = scrollY + viewPortHeight - nOverlayOffsetHeight - nViewportOffset,
3714
 
 
3715
 
                yNew = y,
3716
 
                
3717
 
                oOverlapPositions = {
3718
 
                    "trbr": true,
3719
 
                    "tlbl": true,
3720
 
                    "bltl": true,
3721
 
                    "brtr": true
3722
 
                };
3723
 
 
3724
 
 
3725
 
            var flipVertical = function () {
3726
 
 
3727
 
                var nNewY;
3728
 
            
3729
 
                // The Overlay is below the context element, flip it above
3730
 
                if ((oOverlay.cfg.getProperty("y") - scrollY) > nContextElY) { 
3731
 
                    nNewY = (nContextElY - nOverlayOffsetHeight);
3732
 
                }
3733
 
                else {  // The Overlay is above the context element, flip it below
3734
 
                    nNewY = (nContextElY + nContextElHeight);
3735
 
                }
3736
 
    
3737
 
                oOverlay.cfg.setProperty("y", (nNewY + scrollY), true);
3738
 
                
3739
 
                return nNewY;
3740
 
            
3741
 
            };
3742
 
 
3743
 
 
3744
 
            /*
3745
 
                 Uses the context element's position to calculate the availble height 
3746
 
                 above and below it to display its corresponding Overlay.
3747
 
            */
3748
 
 
3749
 
            var getDisplayRegionHeight = function () {
3750
 
 
3751
 
                // The Overlay is below the context element
3752
 
                if ((oOverlay.cfg.getProperty("y") - scrollY) > nContextElY) {
3753
 
                    return (nBottomRegionHeight - nViewportOffset);                             
3754
 
                }
3755
 
                else {  // The Overlay is above the context element
3756
 
                    return (nTopRegionHeight - nViewportOffset);                                
3757
 
                }
3758
 
        
3759
 
            };
3760
 
 
3761
 
 
3762
 
            /*
3763
 
                Trys to place the Overlay in the best possible position (either above or 
3764
 
                below its corresponding context element).
3765
 
            */
3766
 
        
3767
 
            var setVerticalPosition = function () {
3768
 
        
3769
 
                var nDisplayRegionHeight = getDisplayRegionHeight(),
3770
 
                    fnReturnVal;
3771
 
                    
3772
 
 
3773
 
                if (nOverlayOffsetHeight > nDisplayRegionHeight) {
3774
 
                   
3775
 
                    if (bFlipped) {
3776
 
        
3777
 
                        /*
3778
 
                             All possible positions and values for the 
3779
 
                             "maxheight" configuration property have been 
3780
 
                             tried, but none were successful, so fall back 
3781
 
                             to the original size and position.
3782
 
                        */
3783
 
    
3784
 
                        flipVertical();
3785
 
                        
3786
 
                    }
3787
 
                    else {
3788
 
        
3789
 
                        flipVertical();
3790
 
 
3791
 
                        bFlipped = true;
3792
 
        
3793
 
                        fnReturnVal = setVerticalPosition();
3794
 
        
3795
 
                    }
3796
 
                
3797
 
                }
3798
 
        
3799
 
                return fnReturnVal;
3800
 
        
3801
 
            };
3802
 
 
3803
 
 
3804
 
            // Determine if the current value for the Overlay's "y" configuration property will
3805
 
            // result in the Overlay being positioned outside the boundaries of the viewport
3806
 
 
3807
 
            if (y < topConstraint || y  > bottomConstraint) {
3808
 
        
3809
 
                // The current value for the Overlay's "y" configuration property WILL
3810
 
                // result in the Overlay being positioned outside the boundaries of the viewport
3811
 
 
3812
 
                if (bCanConstrain) {    
3813
 
 
3814
 
                    //  If the "preventcontextoverlap" configuration property is set to "true", 
3815
 
                    //  try to flip the Overlay to both keep it inside the boundaries of the 
3816
 
                    //  viewport AND from overlaping its context element.
3817
 
        
3818
 
                    if (this.cfg.getProperty("preventcontextoverlap") && aContext && 
3819
 
                        oOverlapPositions[(aContext[1] + aContext[2])]) {
3820
 
        
3821
 
                        oContextEl = aContext[0];
3822
 
                        nContextElHeight = oContextEl.offsetHeight;
3823
 
                        nContextElY = (Dom.getY(oContextEl) - scrollY);
3824
 
        
3825
 
                        nTopRegionHeight = nContextElY;
3826
 
                        nBottomRegionHeight = (viewPortHeight - (nContextElY + nContextElHeight));
3827
 
        
3828
 
                        setVerticalPosition();
3829
 
        
3830
 
                        yNew = oOverlay.cfg.getProperty("y");
3831
 
        
3832
 
                    }
3833
 
                    else {
3834
 
 
3835
 
                        if (y < topConstraint) {
3836
 
                            yNew  = topConstraint;
3837
 
                        } else if (y  > bottomConstraint) {
3838
 
                            yNew  = bottomConstraint;
3839
 
                        }
3840
 
                    
3841
 
                    }
3842
 
                
3843
 
                }
3844
 
                else {
3845
 
                
3846
 
                    //  The "y" configuration property cannot be set to a value that will keep
3847
 
                    //  entire Overlay inside the boundary of the viewport.  Therefore, set  
3848
 
                    //  the "y" configuration property to scrollY to keep as much of the 
3849
 
                    //  Overlay inside the viewport as possible.
3850
 
                
3851
 
                    yNew = nViewportOffset + scrollY;
3852
 
                }
3853
 
        
3854
 
            }
3855
 
 
3856
 
            return yNew;
3857
 
        },
3858
 
 
3859
 
 
3860
 
        /**
3861
 
         * Given x, y coordinate values, returns the calculated coordinates required to 
3862
 
         * position the Overlay if it is to be constrained to the viewport, based on the 
3863
 
         * current element size, viewport dimensions and scroll values.
3864
 
         *
3865
 
         * @param {Number} x The X coordinate value to be constrained
3866
 
         * @param {Number} y The Y coordinate value to be constrained
3867
 
         * @return {Array} The constrained x and y coordinates at index 0 and 1 respectively;
3868
 
         */
3869
 
        getConstrainedXY: function(x, y) {
3870
 
            return [this.getConstrainedX(x), this.getConstrainedY(y)];
3871
 
        },
3872
 
 
3873
 
        /**
3874
 
        * Centers the container in the viewport.
3875
 
        * @method center
3876
 
        */
3877
 
        center: function () {
3878
 
 
3879
 
            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
3880
 
                elementWidth = this.element.offsetWidth,
3881
 
                elementHeight = this.element.offsetHeight,
3882
 
                viewPortWidth = Dom.getViewportWidth(),
3883
 
                viewPortHeight = Dom.getViewportHeight(),
3884
 
                x,
3885
 
                y;
3886
 
 
3887
 
            if (elementWidth < viewPortWidth) {
3888
 
                x = (viewPortWidth / 2) - (elementWidth / 2) + Dom.getDocumentScrollLeft();
3889
 
            } else {
3890
 
                x = nViewportOffset + Dom.getDocumentScrollLeft();
3891
 
            }
3892
 
 
3893
 
            if (elementHeight < viewPortHeight) {
3894
 
                y = (viewPortHeight / 2) - (elementHeight / 2) + Dom.getDocumentScrollTop();
3895
 
            } else {
3896
 
                y = nViewportOffset + Dom.getDocumentScrollTop();
3897
 
            }
3898
 
 
3899
 
            this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
3900
 
            this.cfg.refireEvent("iframe");
3901
 
 
3902
 
            if (UA.webkit) {
3903
 
                this.forceContainerRedraw();
3904
 
            }
3905
 
        },
3906
 
 
3907
 
        /**
3908
 
        * Synchronizes the Panel's "xy", "x", and "y" properties with the 
3909
 
        * Panel's position in the DOM. This is primarily used to update  
3910
 
        * position information during drag & drop.
3911
 
        * @method syncPosition
3912
 
        */
3913
 
        syncPosition: function () {
3914
 
 
3915
 
            var pos = Dom.getXY(this.element);
3916
 
 
3917
 
            this.cfg.setProperty("x", pos[0], true);
3918
 
            this.cfg.setProperty("y", pos[1], true);
3919
 
            this.cfg.setProperty("xy", pos, true);
3920
 
 
3921
 
        },
3922
 
 
3923
 
        /**
3924
 
        * Event handler fired when the resize monitor element is resized.
3925
 
        * @method onDomResize
3926
 
        * @param {DOMEvent} e The resize DOM event
3927
 
        * @param {Object} obj The scope object
3928
 
        */
3929
 
        onDomResize: function (e, obj) {
3930
 
 
3931
 
            var me = this;
3932
 
 
3933
 
            Overlay.superclass.onDomResize.call(this, e, obj);
3934
 
 
3935
 
            setTimeout(function () {
3936
 
                me.syncPosition();
3937
 
                me.cfg.refireEvent("iframe");
3938
 
                me.cfg.refireEvent("context");
3939
 
            }, 0);
3940
 
        },
3941
 
 
3942
 
        /**
3943
 
         * Determines the content box height of the given element (height of the element, without padding or borders) in pixels.
3944
 
         *
3945
 
         * @method _getComputedHeight
3946
 
         * @private
3947
 
         * @param {HTMLElement} el The element for which the content height needs to be determined
3948
 
         * @return {Number} The content box height of the given element, or null if it could not be determined.
3949
 
         */
3950
 
        _getComputedHeight : (function() {
3951
 
 
3952
 
            if (document.defaultView && document.defaultView.getComputedStyle) {
3953
 
                return function(el) {
3954
 
                    var height = null;
3955
 
                    if (el.ownerDocument && el.ownerDocument.defaultView) {
3956
 
                        var computed = el.ownerDocument.defaultView.getComputedStyle(el, '');
3957
 
                        if (computed) {
3958
 
                            height = parseInt(computed.height, 10);
3959
 
                        }
3960
 
                    }
3961
 
                    return (Lang.isNumber(height)) ? height : null;
3962
 
                };
3963
 
            } else {
3964
 
                return function(el) {
3965
 
                    var height = null;
3966
 
                    if (el.style.pixelHeight) {
3967
 
                        height = el.style.pixelHeight;
3968
 
                    }
3969
 
                    return (Lang.isNumber(height)) ? height : null;
3970
 
                };
3971
 
            }
3972
 
        })(),
3973
 
 
3974
 
        /**
3975
 
         * autofillheight validator. Verifies that the autofill value is either null 
3976
 
         * or one of the strings : "body", "header" or "footer".
3977
 
         *
3978
 
         * @method _validateAutoFillHeight
3979
 
         * @protected
3980
 
         * @param {String} val
3981
 
         * @return true, if valid, false otherwise
3982
 
         */
3983
 
        _validateAutoFillHeight : function(val) {
3984
 
            return (!val) || (Lang.isString(val) && Overlay.STD_MOD_RE.test(val));
3985
 
        },
3986
 
 
3987
 
        /**
3988
 
         * The default custom event handler executed when the overlay's height is changed, 
3989
 
         * if the autofillheight property has been set.
3990
 
         *
3991
 
         * @method _autoFillOnHeightChange
3992
 
         * @protected
3993
 
         * @param {String} type The event type
3994
 
         * @param {Array} args The array of arguments passed to event subscribers
3995
 
         * @param {HTMLElement} el The header, body or footer element which is to be resized to fill
3996
 
         * out the containers height
3997
 
         */
3998
 
        _autoFillOnHeightChange : function(type, args, el) {
3999
 
            var height = this.cfg.getProperty("height");
4000
 
            if ((height && height !== "auto") || (height === 0)) {
4001
 
                this.fillHeight(el);
4002
 
            }
4003
 
        },
4004
 
 
4005
 
        /**
4006
 
         * Returns the sub-pixel height of the el, using getBoundingClientRect, if available,
4007
 
         * otherwise returns the offsetHeight
4008
 
         * @method _getPreciseHeight
4009
 
         * @private
4010
 
         * @param {HTMLElement} el
4011
 
         * @return {Float} The sub-pixel height if supported by the browser, else the rounded height.
4012
 
         */
4013
 
        _getPreciseHeight : function(el) {
4014
 
            var height = el.offsetHeight;
4015
 
 
4016
 
            if (el.getBoundingClientRect) {
4017
 
                var rect = el.getBoundingClientRect();
4018
 
                height = rect.bottom - rect.top;
4019
 
            }
4020
 
 
4021
 
            return height;
4022
 
        },
4023
 
 
4024
 
        /**
4025
 
         * <p>
4026
 
         * Sets the height on the provided header, body or footer element to 
4027
 
         * fill out the height of the container. It determines the height of the 
4028
 
         * containers content box, based on it's configured height value, and 
4029
 
         * sets the height of the autofillheight element to fill out any 
4030
 
         * space remaining after the other standard module element heights 
4031
 
         * have been accounted for.
4032
 
         * </p>
4033
 
         * <p><strong>NOTE:</strong> This method is not designed to work if an explicit 
4034
 
         * height has not been set on the container, since for an "auto" height container, 
4035
 
         * the heights of the header/body/footer will drive the height of the container.</p>
4036
 
         *
4037
 
         * @method fillHeight
4038
 
         * @param {HTMLElement} el The element which should be resized to fill out the height
4039
 
         * of the container element.
4040
 
         */
4041
 
        fillHeight : function(el) {
4042
 
            if (el) {
4043
 
                var container = this.innerElement || this.element,
4044
 
                    containerEls = [this.header, this.body, this.footer],
4045
 
                    containerEl,
4046
 
                    total = 0,
4047
 
                    filled = 0,
4048
 
                    remaining = 0,
4049
 
                    validEl = false;
4050
 
 
4051
 
                for (var i = 0, l = containerEls.length; i < l; i++) {
4052
 
                    containerEl = containerEls[i];
4053
 
                    if (containerEl) {
4054
 
                        if (el !== containerEl) {
4055
 
                            filled += this._getPreciseHeight(containerEl);
4056
 
                        } else {
4057
 
                            validEl = true;
4058
 
                        }
4059
 
                    }
4060
 
                }
4061
 
 
4062
 
                if (validEl) {
4063
 
 
4064
 
                    if (UA.ie || UA.opera) {
4065
 
                        // Need to set height to 0, to allow height to be reduced
4066
 
                        Dom.setStyle(el, 'height', 0 + 'px');
4067
 
                    }
4068
 
 
4069
 
                    total = this._getComputedHeight(container);
4070
 
 
4071
 
                    // Fallback, if we can't get computed value for content height
4072
 
                    if (total === null) {
4073
 
                        Dom.addClass(container, "yui-override-padding");
4074
 
                        total = container.clientHeight; // Content, No Border, 0 Padding (set by yui-override-padding)
4075
 
                        Dom.removeClass(container, "yui-override-padding");
4076
 
                    }
4077
 
    
4078
 
                    remaining = Math.max(total - filled, 0);
4079
 
    
4080
 
                    Dom.setStyle(el, "height", remaining + "px");
4081
 
    
4082
 
                    // Re-adjust height if required, to account for el padding and border
4083
 
                    if (el.offsetHeight != remaining) {
4084
 
                        remaining = Math.max(remaining - (el.offsetHeight - remaining), 0);
4085
 
                    }
4086
 
                    Dom.setStyle(el, "height", remaining + "px");
4087
 
                }
4088
 
            }
4089
 
        },
4090
 
 
4091
 
        /**
4092
 
        * Places the Overlay on top of all other instances of 
4093
 
        * YAHOO.widget.Overlay.
4094
 
        * @method bringToTop
4095
 
        */
4096
 
        bringToTop: function () {
4097
 
 
4098
 
            var aOverlays = [],
4099
 
                oElement = this.element;
4100
 
 
4101
 
            function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
4102
 
 
4103
 
                var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
4104
 
                    sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
4105
 
 
4106
 
                    nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 0 : parseInt(sZIndex1, 10),
4107
 
                    nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 0 : parseInt(sZIndex2, 10);
4108
 
 
4109
 
                if (nZIndex1 > nZIndex2) {
4110
 
                    return -1;
4111
 
                } else if (nZIndex1 < nZIndex2) {
4112
 
                    return 1;
4113
 
                } else {
4114
 
                    return 0;
4115
 
                }
4116
 
            }
4117
 
 
4118
 
            function isOverlayElement(p_oElement) {
4119
 
 
4120
 
                var isOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
4121
 
                    Panel = YAHOO.widget.Panel;
4122
 
 
4123
 
                if (isOverlay && !Dom.isAncestor(oElement, p_oElement)) {
4124
 
                    if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
4125
 
                        aOverlays[aOverlays.length] = p_oElement.parentNode;
4126
 
                    } else {
4127
 
                        aOverlays[aOverlays.length] = p_oElement;
4128
 
                    }
4129
 
                }
4130
 
            }
4131
 
 
4132
 
            Dom.getElementsBy(isOverlayElement, "DIV", document.body);
4133
 
 
4134
 
            aOverlays.sort(compareZIndexDesc);
4135
 
 
4136
 
            var oTopOverlay = aOverlays[0],
4137
 
                nTopZIndex;
4138
 
 
4139
 
            if (oTopOverlay) {
4140
 
                nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
4141
 
 
4142
 
                if (!isNaN(nTopZIndex)) {
4143
 
                    var bRequiresBump = false;
4144
 
 
4145
 
                    if (oTopOverlay != oElement) {
4146
 
                        bRequiresBump = true;
4147
 
                    } else if (aOverlays.length > 1) {
4148
 
                        var nNextZIndex = Dom.getStyle(aOverlays[1], "zIndex");
4149
 
                        // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4150
 
                        if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4151
 
                            bRequiresBump = true;
4152
 
                        }
4153
 
                    }
4154
 
                    if (bRequiresBump) {
4155
 
                        this.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4156
 
                    }
4157
 
                }
4158
 
            }
4159
 
        },
4160
 
 
4161
 
        /**
4162
 
        * Removes the Overlay element from the DOM and sets all child 
4163
 
        * elements to null.
4164
 
        * @method destroy
4165
 
        */
4166
 
        destroy: function () {
4167
 
 
4168
 
            if (this.iframe) {
4169
 
                this.iframe.parentNode.removeChild(this.iframe);
4170
 
            }
4171
 
 
4172
 
            this.iframe = null;
4173
 
 
4174
 
            Overlay.windowResizeEvent.unsubscribe(
4175
 
                this.doCenterOnDOMEvent, this);
4176
 
    
4177
 
            Overlay.windowScrollEvent.unsubscribe(
4178
 
                this.doCenterOnDOMEvent, this);
4179
 
 
4180
 
            Module.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);
4181
 
 
4182
 
            Overlay.superclass.destroy.call(this);
4183
 
        },
4184
 
 
4185
 
        /**
4186
 
         * Can be used to force the container to repaint/redraw it's contents.
4187
 
         * <p>
4188
 
         * By default applies and then removes a 1px bottom margin through the 
4189
 
         * application/removal of a "yui-force-redraw" class.
4190
 
         * </p>
4191
 
         * <p>
4192
 
         * It is currently used by Overlay to force a repaint for webkit 
4193
 
         * browsers, when centering.
4194
 
         * </p>
4195
 
         * @method forceContainerRedraw
4196
 
         */
4197
 
        forceContainerRedraw : function() {
4198
 
            var c = this;
4199
 
            Dom.addClass(c.element, "yui-force-redraw");
4200
 
            setTimeout(function() {
4201
 
                Dom.removeClass(c.element, "yui-force-redraw");
4202
 
            }, 0);
4203
 
        },
4204
 
 
4205
 
        /**
4206
 
        * Returns a String representation of the object.
4207
 
        * @method toString
4208
 
        * @return {String} The string representation of the Overlay.
4209
 
        */
4210
 
        toString: function () {
4211
 
            return "Overlay " + this.id;
4212
 
        }
4213
 
 
4214
 
    });
4215
 
}());
4216
 
 
4217
 
(function () {
4218
 
 
4219
 
    /**
4220
 
    * OverlayManager is used for maintaining the focus status of 
4221
 
    * multiple Overlays.
4222
 
    * @namespace YAHOO.widget
4223
 
    * @namespace YAHOO.widget
4224
 
    * @class OverlayManager
4225
 
    * @constructor
4226
 
    * @param {Array} overlays Optional. A collection of Overlays to register 
4227
 
    * with the manager.
4228
 
    * @param {Object} userConfig  The object literal representing the user 
4229
 
    * configuration of the OverlayManager
4230
 
    */
4231
 
    YAHOO.widget.OverlayManager = function (userConfig) {
4232
 
        this.init(userConfig);
4233
 
    };
4234
 
 
4235
 
    var Overlay = YAHOO.widget.Overlay,
4236
 
        Event = YAHOO.util.Event,
4237
 
        Dom = YAHOO.util.Dom,
4238
 
        Config = YAHOO.util.Config,
4239
 
        CustomEvent = YAHOO.util.CustomEvent,
4240
 
        OverlayManager = YAHOO.widget.OverlayManager;
4241
 
 
4242
 
    /**
4243
 
    * The CSS class representing a focused Overlay
4244
 
    * @property OverlayManager.CSS_FOCUSED
4245
 
    * @static
4246
 
    * @final
4247
 
    * @type String
4248
 
    */
4249
 
    OverlayManager.CSS_FOCUSED = "focused";
4250
 
 
4251
 
    OverlayManager.prototype = {
4252
 
 
4253
 
        /**
4254
 
        * The class's constructor function
4255
 
        * @property contructor
4256
 
        * @type Function
4257
 
        */
4258
 
        constructor: OverlayManager,
4259
 
 
4260
 
        /**
4261
 
        * The array of Overlays that are currently registered
4262
 
        * @property overlays
4263
 
        * @type YAHOO.widget.Overlay[]
4264
 
        */
4265
 
        overlays: null,
4266
 
 
4267
 
        /**
4268
 
        * Initializes the default configuration of the OverlayManager
4269
 
        * @method initDefaultConfig
4270
 
        */
4271
 
        initDefaultConfig: function () {
4272
 
            /**
4273
 
            * The collection of registered Overlays in use by 
4274
 
            * the OverlayManager
4275
 
            * @config overlays
4276
 
            * @type YAHOO.widget.Overlay[]
4277
 
            * @default null
4278
 
            */
4279
 
            this.cfg.addProperty("overlays", { suppressEvent: true } );
4280
 
 
4281
 
            /**
4282
 
            * The default DOM event that should be used to focus an Overlay
4283
 
            * @config focusevent
4284
 
            * @type String
4285
 
            * @default "mousedown"
4286
 
            */
4287
 
            this.cfg.addProperty("focusevent", { value: "mousedown" } );
4288
 
        },
4289
 
 
4290
 
        /**
4291
 
        * Initializes the OverlayManager
4292
 
        * @method init
4293
 
        * @param {Overlay[]} overlays Optional. A collection of Overlays to 
4294
 
        * register with the manager.
4295
 
        * @param {Object} userConfig  The object literal representing the user 
4296
 
        * configuration of the OverlayManager
4297
 
        */
4298
 
        init: function (userConfig) {
4299
 
 
4300
 
            /**
4301
 
            * The OverlayManager's Config object used for monitoring 
4302
 
            * configuration properties.
4303
 
            * @property cfg
4304
 
            * @type Config
4305
 
            */
4306
 
            this.cfg = new Config(this);
4307
 
 
4308
 
            this.initDefaultConfig();
4309
 
 
4310
 
            if (userConfig) {
4311
 
                this.cfg.applyConfig(userConfig, true);
4312
 
            }
4313
 
            this.cfg.fireQueue();
4314
 
 
4315
 
            /**
4316
 
            * The currently activated Overlay
4317
 
            * @property activeOverlay
4318
 
            * @private
4319
 
            * @type YAHOO.widget.Overlay
4320
 
            */
4321
 
            var activeOverlay = null;
4322
 
 
4323
 
            /**
4324
 
            * Returns the currently focused Overlay
4325
 
            * @method getActive
4326
 
            * @return {Overlay} The currently focused Overlay
4327
 
            */
4328
 
            this.getActive = function () {
4329
 
                return activeOverlay;
4330
 
            };
4331
 
 
4332
 
            /**
4333
 
            * Focuses the specified Overlay
4334
 
            * @method focus
4335
 
            * @param {Overlay} overlay The Overlay to focus
4336
 
            * @param {String} overlay The id of the Overlay to focus
4337
 
            */
4338
 
            this.focus = function (overlay) {
4339
 
                var o = this.find(overlay);
4340
 
                if (o) {
4341
 
                    o.focus();
4342
 
                }
4343
 
            };
4344
 
 
4345
 
            /**
4346
 
            * Removes the specified Overlay from the manager
4347
 
            * @method remove
4348
 
            * @param {Overlay} overlay The Overlay to remove
4349
 
            * @param {String} overlay The id of the Overlay to remove
4350
 
            */
4351
 
            this.remove = function (overlay) {
4352
 
 
4353
 
                var o = this.find(overlay), 
4354
 
                        originalZ;
4355
 
 
4356
 
                if (o) {
4357
 
                    if (activeOverlay == o) {
4358
 
                        activeOverlay = null;
4359
 
                    }
4360
 
 
4361
 
                    var bDestroyed = (o.element === null && o.cfg === null) ? true : false;
4362
 
 
4363
 
                    if (!bDestroyed) {
4364
 
                        // Set it's zindex so that it's sorted to the end.
4365
 
                        originalZ = Dom.getStyle(o.element, "zIndex");
4366
 
                        o.cfg.setProperty("zIndex", -1000, true);
4367
 
                    }
4368
 
 
4369
 
                    this.overlays.sort(this.compareZIndexDesc);
4370
 
                    this.overlays = this.overlays.slice(0, (this.overlays.length - 1));
4371
 
 
4372
 
                    o.hideEvent.unsubscribe(o.blur);
4373
 
                    o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
4374
 
                    o.focusEvent.unsubscribe(this._onOverlayFocusHandler, o);
4375
 
                    o.blurEvent.unsubscribe(this._onOverlayBlurHandler, o);
4376
 
 
4377
 
                    if (!bDestroyed) {
4378
 
                        Event.removeListener(o.element, this.cfg.getProperty("focusevent"), this._onOverlayElementFocus);
4379
 
                        o.cfg.setProperty("zIndex", originalZ, true);
4380
 
                        o.cfg.setProperty("manager", null);
4381
 
                    }
4382
 
 
4383
 
                    /* _managed Flag for custom or existing. Don't want to remove existing */
4384
 
                    if (o.focusEvent._managed) { o.focusEvent = null; }
4385
 
                    if (o.blurEvent._managed) { o.blurEvent = null; }
4386
 
 
4387
 
                    if (o.focus._managed) { o.focus = null; }
4388
 
                    if (o.blur._managed) { o.blur = null; }
4389
 
                }
4390
 
            };
4391
 
 
4392
 
            /**
4393
 
            * Removes focus from all registered Overlays in the manager
4394
 
            * @method blurAll
4395
 
            */
4396
 
            this.blurAll = function () {
4397
 
 
4398
 
                var nOverlays = this.overlays.length,
4399
 
                    i;
4400
 
 
4401
 
                if (nOverlays > 0) {
4402
 
                    i = nOverlays - 1;
4403
 
                    do {
4404
 
                        this.overlays[i].blur();
4405
 
                    }
4406
 
                    while(i--);
4407
 
                }
4408
 
            };
4409
 
 
4410
 
            /**
4411
 
             * Updates the state of the OverlayManager and overlay, as a result of the overlay
4412
 
             * being blurred.
4413
 
             * 
4414
 
             * @method _manageBlur
4415
 
             * @param {Overlay} overlay The overlay instance which got blurred.
4416
 
             * @protected
4417
 
             */
4418
 
            this._manageBlur = function (overlay) {
4419
 
                var changed = false;
4420
 
                if (activeOverlay == overlay) {
4421
 
                    Dom.removeClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4422
 
                    activeOverlay = null;
4423
 
                    changed = true;
4424
 
                }
4425
 
                return changed;
4426
 
            };
4427
 
 
4428
 
            /**
4429
 
             * Updates the state of the OverlayManager and overlay, as a result of the overlay 
4430
 
             * receiving focus.
4431
 
             *
4432
 
             * @method _manageFocus
4433
 
             * @param {Overlay} overlay The overlay instance which got focus.
4434
 
             * @protected
4435
 
             */
4436
 
            this._manageFocus = function(overlay) {
4437
 
                var changed = false;
4438
 
                if (activeOverlay != overlay) {
4439
 
                    if (activeOverlay) {
4440
 
                        activeOverlay.blur();
4441
 
                    }
4442
 
                    activeOverlay = overlay;
4443
 
                    this.bringToTop(activeOverlay);
4444
 
                    Dom.addClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
4445
 
                    changed = true;
4446
 
                }
4447
 
                return changed;
4448
 
            };
4449
 
 
4450
 
            var overlays = this.cfg.getProperty("overlays");
4451
 
 
4452
 
            if (! this.overlays) {
4453
 
                this.overlays = [];
4454
 
            }
4455
 
 
4456
 
            if (overlays) {
4457
 
                this.register(overlays);
4458
 
                this.overlays.sort(this.compareZIndexDesc);
4459
 
            }
4460
 
        },
4461
 
 
4462
 
        /**
4463
 
        * @method _onOverlayElementFocus
4464
 
        * @description Event handler for the DOM event that is used to focus 
4465
 
        * the Overlay instance as specified by the "focusevent" 
4466
 
        * configuration property.
4467
 
        * @private
4468
 
        * @param {Event} p_oEvent Object representing the DOM event 
4469
 
        * object passed back by the event utility (Event).
4470
 
        */
4471
 
        _onOverlayElementFocus: function (p_oEvent) {
4472
 
 
4473
 
            var oTarget = Event.getTarget(p_oEvent),
4474
 
                oClose = this.close;
4475
 
 
4476
 
            if (oClose && (oTarget == oClose || Dom.isAncestor(oClose, oTarget))) {
4477
 
                this.blur();
4478
 
            } else {
4479
 
                this.focus();
4480
 
            }
4481
 
        },
4482
 
 
4483
 
        /**
4484
 
        * @method _onOverlayDestroy
4485
 
        * @description "destroy" event handler for the Overlay.
4486
 
        * @private
4487
 
        * @param {String} p_sType String representing the name of the event  
4488
 
        * that was fired.
4489
 
        * @param {Array} p_aArgs Array of arguments sent when the event 
4490
 
        * was fired.
4491
 
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4492
 
        * fired the event.
4493
 
        */
4494
 
        _onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
4495
 
            this.remove(p_oOverlay);
4496
 
        },
4497
 
 
4498
 
        /**
4499
 
        * @method _onOverlayFocusHandler
4500
 
        *
4501
 
        * focusEvent Handler, used to delegate to _manageFocus with the 
4502
 
        * correct arguments.
4503
 
        *
4504
 
        * @private
4505
 
        * @param {String} p_sType String representing the name of the event  
4506
 
        * that was fired.
4507
 
        * @param {Array} p_aArgs Array of arguments sent when the event 
4508
 
        * was fired.
4509
 
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4510
 
        * fired the event.
4511
 
        */
4512
 
        _onOverlayFocusHandler: function(p_sType, p_aArgs, p_oOverlay) {
4513
 
            this._manageFocus(p_oOverlay);
4514
 
        },
4515
 
 
4516
 
        /**
4517
 
        * @method _onOverlayBlurHandler
4518
 
        *
4519
 
        * blurEvent Handler, used to delegate to _manageBlur with the 
4520
 
        * correct arguments.
4521
 
        *
4522
 
        * @private
4523
 
        * @param {String} p_sType String representing the name of the event  
4524
 
        * that was fired.
4525
 
        * @param {Array} p_aArgs Array of arguments sent when the event 
4526
 
        * was fired.
4527
 
        * @param {Overlay} p_oOverlay Object representing the overlay that 
4528
 
        * fired the event.
4529
 
        */
4530
 
        _onOverlayBlurHandler: function(p_sType, p_aArgs, p_oOverlay) {
4531
 
            this._manageBlur(p_oOverlay);
4532
 
        },
4533
 
 
4534
 
        /**
4535
 
         * Subscribes to the Overlay based instance focusEvent, to allow the OverlayManager to
4536
 
         * monitor focus state.
4537
 
         * 
4538
 
         * If the instance already has a focusEvent (e.g. Menu), OverlayManager will subscribe 
4539
 
         * to the existing focusEvent, however if a focusEvent or focus method does not exist
4540
 
         * on the instance, the _bindFocus method will add them, and the focus method will 
4541
 
         * update the OverlayManager's state directly.
4542
 
         * 
4543
 
         * @method _bindFocus
4544
 
         * @param {Overlay} overlay The overlay for which focus needs to be managed
4545
 
         * @protected
4546
 
         */
4547
 
        _bindFocus : function(overlay) {
4548
 
            var mgr = this;
4549
 
 
4550
 
            if (!overlay.focusEvent) {
4551
 
                overlay.focusEvent = overlay.createEvent("focus");
4552
 
                overlay.focusEvent.signature = CustomEvent.LIST;
4553
 
                overlay.focusEvent._managed = true;
4554
 
            } else {
4555
 
                overlay.focusEvent.subscribe(mgr._onOverlayFocusHandler, overlay, mgr);
4556
 
            }
4557
 
 
4558
 
            if (!overlay.focus) {
4559
 
                Event.on(overlay.element, mgr.cfg.getProperty("focusevent"), mgr._onOverlayElementFocus, null, overlay);
4560
 
                overlay.focus = function () {
4561
 
                    if (mgr._manageFocus(this)) {
4562
 
                        // For Panel/Dialog
4563
 
                        if (this.cfg.getProperty("visible") && this.focusFirst) {
4564
 
                            this.focusFirst();
4565
 
                        }
4566
 
                        this.focusEvent.fire();
4567
 
                    }
4568
 
                };
4569
 
                overlay.focus._managed = true;
4570
 
            }
4571
 
        },
4572
 
 
4573
 
        /**
4574
 
         * Subscribes to the Overlay based instance's blurEvent to allow the OverlayManager to
4575
 
         * monitor blur state.
4576
 
         *
4577
 
         * If the instance already has a blurEvent (e.g. Menu), OverlayManager will subscribe 
4578
 
         * to the existing blurEvent, however if a blurEvent or blur method does not exist
4579
 
         * on the instance, the _bindBlur method will add them, and the blur method 
4580
 
         * update the OverlayManager's state directly.
4581
 
         *
4582
 
         * @method _bindBlur
4583
 
         * @param {Overlay} overlay The overlay for which blur needs to be managed
4584
 
         * @protected
4585
 
         */
4586
 
        _bindBlur : function(overlay) {
4587
 
            var mgr = this;
4588
 
 
4589
 
            if (!overlay.blurEvent) {
4590
 
                overlay.blurEvent = overlay.createEvent("blur");
4591
 
                overlay.blurEvent.signature = CustomEvent.LIST;
4592
 
                overlay.focusEvent._managed = true;
4593
 
            } else {
4594
 
                overlay.blurEvent.subscribe(mgr._onOverlayBlurHandler, overlay, mgr);
4595
 
            }
4596
 
 
4597
 
            if (!overlay.blur) {
4598
 
                overlay.blur = function () {
4599
 
                    if (mgr._manageBlur(this)) {
4600
 
                        this.blurEvent.fire();
4601
 
                    }
4602
 
                };
4603
 
                overlay.blur._managed = true;
4604
 
            }
4605
 
 
4606
 
            overlay.hideEvent.subscribe(overlay.blur);
4607
 
        },
4608
 
 
4609
 
        /**
4610
 
         * Subscribes to the Overlay based instance's destroyEvent, to allow the Overlay
4611
 
         * to be removed for the OverlayManager when destroyed.
4612
 
         * 
4613
 
         * @method _bindDestroy
4614
 
         * @param {Overlay} overlay The overlay instance being managed
4615
 
         * @protected
4616
 
         */
4617
 
        _bindDestroy : function(overlay) {
4618
 
            var mgr = this;
4619
 
            overlay.destroyEvent.subscribe(mgr._onOverlayDestroy, overlay, mgr);
4620
 
        },
4621
 
 
4622
 
        /**
4623
 
         * Ensures the zIndex configuration property on the managed overlay based instance
4624
 
         * is set to the computed zIndex value from the DOM (with "auto" translating to 0).
4625
 
         *
4626
 
         * @method _syncZIndex
4627
 
         * @param {Overlay} overlay The overlay instance being managed
4628
 
         * @protected
4629
 
         */
4630
 
        _syncZIndex : function(overlay) {
4631
 
            var zIndex = Dom.getStyle(overlay.element, "zIndex");
4632
 
            if (!isNaN(zIndex)) {
4633
 
                overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
4634
 
            } else {
4635
 
                overlay.cfg.setProperty("zIndex", 0);
4636
 
            }
4637
 
        },
4638
 
 
4639
 
        /**
4640
 
        * Registers an Overlay or an array of Overlays with the manager. Upon 
4641
 
        * registration, the Overlay receives functions for focus and blur, 
4642
 
        * along with CustomEvents for each.
4643
 
        *
4644
 
        * @method register
4645
 
        * @param {Overlay} overlay  An Overlay to register with the manager.
4646
 
        * @param {Overlay[]} overlay  An array of Overlays to register with 
4647
 
        * the manager.
4648
 
        * @return {boolean} true if any Overlays are registered.
4649
 
        */
4650
 
        register: function (overlay) {
4651
 
 
4652
 
            var registered = false,
4653
 
                i,
4654
 
                n;
4655
 
 
4656
 
            if (overlay instanceof Overlay) {
4657
 
 
4658
 
                overlay.cfg.addProperty("manager", { value: this } );
4659
 
 
4660
 
                this._bindFocus(overlay);
4661
 
                this._bindBlur(overlay);
4662
 
                this._bindDestroy(overlay);
4663
 
                this._syncZIndex(overlay);
4664
 
 
4665
 
                this.overlays.push(overlay);
4666
 
                this.bringToTop(overlay);
4667
 
 
4668
 
                registered = true;
4669
 
 
4670
 
            } else if (overlay instanceof Array) {
4671
 
 
4672
 
                for (i = 0, n = overlay.length; i < n; i++) {
4673
 
                    registered = this.register(overlay[i]) || registered;
4674
 
                }
4675
 
 
4676
 
            }
4677
 
 
4678
 
            return registered;
4679
 
        },
4680
 
 
4681
 
        /**
4682
 
        * Places the specified Overlay instance on top of all other 
4683
 
        * Overlay instances.
4684
 
        * @method bringToTop
4685
 
        * @param {YAHOO.widget.Overlay} p_oOverlay Object representing an 
4686
 
        * Overlay instance.
4687
 
        * @param {String} p_oOverlay String representing the id of an 
4688
 
        * Overlay instance.
4689
 
        */        
4690
 
        bringToTop: function (p_oOverlay) {
4691
 
 
4692
 
            var oOverlay = this.find(p_oOverlay),
4693
 
                nTopZIndex,
4694
 
                oTopOverlay,
4695
 
                aOverlays;
4696
 
 
4697
 
            if (oOverlay) {
4698
 
 
4699
 
                aOverlays = this.overlays;
4700
 
                aOverlays.sort(this.compareZIndexDesc);
4701
 
 
4702
 
                oTopOverlay = aOverlays[0];
4703
 
 
4704
 
                if (oTopOverlay) {
4705
 
                    nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
4706
 
 
4707
 
                    if (!isNaN(nTopZIndex)) {
4708
 
 
4709
 
                        var bRequiresBump = false;
4710
 
 
4711
 
                        if (oTopOverlay !== oOverlay) {
4712
 
                            bRequiresBump = true;
4713
 
                        } else if (aOverlays.length > 1) {
4714
 
                            var nNextZIndex = Dom.getStyle(aOverlays[1].element, "zIndex");
4715
 
                            // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
4716
 
                            if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
4717
 
                                bRequiresBump = true;
4718
 
                            }
4719
 
                        }
4720
 
 
4721
 
                        if (bRequiresBump) {
4722
 
                            oOverlay.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
4723
 
                        }
4724
 
                    }
4725
 
                    aOverlays.sort(this.compareZIndexDesc);
4726
 
                }
4727
 
            }
4728
 
        },
4729
 
 
4730
 
        /**
4731
 
        * Attempts to locate an Overlay by instance or ID.
4732
 
        * @method find
4733
 
        * @param {Overlay} overlay  An Overlay to locate within the manager
4734
 
        * @param {String} overlay  An Overlay id to locate within the manager
4735
 
        * @return {Overlay} The requested Overlay, if found, or null if it 
4736
 
        * cannot be located.
4737
 
        */
4738
 
        find: function (overlay) {
4739
 
 
4740
 
            var isInstance = overlay instanceof Overlay,
4741
 
                overlays = this.overlays,
4742
 
                n = overlays.length,
4743
 
                found = null,
4744
 
                o,
4745
 
                i;
4746
 
 
4747
 
            if (isInstance || typeof overlay == "string") {
4748
 
                for (i = n-1; i >= 0; i--) {
4749
 
                    o = overlays[i];
4750
 
                    if ((isInstance && (o === overlay)) || (o.id == overlay)) {
4751
 
                        found = o;
4752
 
                        break;
4753
 
                    }
4754
 
                }
4755
 
            }
4756
 
 
4757
 
            return found;
4758
 
        },
4759
 
 
4760
 
        /**
4761
 
        * Used for sorting the manager's Overlays by z-index.
4762
 
        * @method compareZIndexDesc
4763
 
        * @private
4764
 
        * @return {Number} 0, 1, or -1, depending on where the Overlay should 
4765
 
        * fall in the stacking order.
4766
 
        */
4767
 
        compareZIndexDesc: function (o1, o2) {
4768
 
 
4769
 
            var zIndex1 = (o1.cfg) ? o1.cfg.getProperty("zIndex") : null, // Sort invalid (destroyed)
4770
 
                zIndex2 = (o2.cfg) ? o2.cfg.getProperty("zIndex") : null; // objects at bottom.
4771
 
 
4772
 
            if (zIndex1 === null && zIndex2 === null) {
4773
 
                return 0;
4774
 
            } else if (zIndex1 === null){
4775
 
                return 1;
4776
 
            } else if (zIndex2 === null) {
4777
 
                return -1;
4778
 
            } else if (zIndex1 > zIndex2) {
4779
 
                return -1;
4780
 
            } else if (zIndex1 < zIndex2) {
4781
 
                return 1;
4782
 
            } else {
4783
 
                return 0;
4784
 
            }
4785
 
        },
4786
 
 
4787
 
        /**
4788
 
        * Shows all Overlays in the manager.
4789
 
        * @method showAll
4790
 
        */
4791
 
        showAll: function () {
4792
 
            var overlays = this.overlays,
4793
 
                n = overlays.length,
4794
 
                i;
4795
 
 
4796
 
            for (i = n - 1; i >= 0; i--) {
4797
 
                overlays[i].show();
4798
 
            }
4799
 
        },
4800
 
 
4801
 
        /**
4802
 
        * Hides all Overlays in the manager.
4803
 
        * @method hideAll
4804
 
        */
4805
 
        hideAll: function () {
4806
 
            var overlays = this.overlays,
4807
 
                n = overlays.length,
4808
 
                i;
4809
 
 
4810
 
            for (i = n - 1; i >= 0; i--) {
4811
 
                overlays[i].hide();
4812
 
            }
4813
 
        },
4814
 
 
4815
 
        /**
4816
 
        * Returns a string representation of the object.
4817
 
        * @method toString
4818
 
        * @return {String} The string representation of the OverlayManager
4819
 
        */
4820
 
        toString: function () {
4821
 
            return "OverlayManager";
4822
 
        }
4823
 
    };
4824
 
}());
4825
 
 
4826
 
(function () {
4827
 
 
4828
 
    /**
4829
 
    * Tooltip is an implementation of Overlay that behaves like an OS tooltip, 
4830
 
    * displaying when the user mouses over a particular element, and 
4831
 
    * disappearing on mouse out.
4832
 
    * @namespace YAHOO.widget
4833
 
    * @class Tooltip
4834
 
    * @extends YAHOO.widget.Overlay
4835
 
    * @constructor
4836
 
    * @param {String} el The element ID representing the Tooltip <em>OR</em>
4837
 
    * @param {HTMLElement} el The element representing the Tooltip
4838
 
    * @param {Object} userConfig The configuration object literal containing 
4839
 
    * the configuration that should be set for this Overlay. See configuration 
4840
 
    * documentation for more details.
4841
 
    */
4842
 
    YAHOO.widget.Tooltip = function (el, userConfig) {
4843
 
        YAHOO.widget.Tooltip.superclass.constructor.call(this, el, userConfig);
4844
 
    };
4845
 
 
4846
 
    var Lang = YAHOO.lang,
4847
 
        Event = YAHOO.util.Event,
4848
 
        CustomEvent = YAHOO.util.CustomEvent,
4849
 
        Dom = YAHOO.util.Dom,
4850
 
        Tooltip = YAHOO.widget.Tooltip,
4851
 
        UA = YAHOO.env.ua,
4852
 
        bIEQuirks = (UA.ie && (UA.ie <= 6 || document.compatMode == "BackCompat")),
4853
 
 
4854
 
        m_oShadowTemplate,
4855
 
 
4856
 
        /**
4857
 
        * Constant representing the Tooltip's configuration properties
4858
 
        * @property DEFAULT_CONFIG
4859
 
        * @private
4860
 
        * @final
4861
 
        * @type Object
4862
 
        */
4863
 
        DEFAULT_CONFIG = {
4864
 
 
4865
 
            "PREVENT_OVERLAP": { 
4866
 
                key: "preventoverlap", 
4867
 
                value: true, 
4868
 
                validator: Lang.isBoolean, 
4869
 
                supercedes: ["x", "y", "xy"] 
4870
 
            },
4871
 
 
4872
 
            "SHOW_DELAY": { 
4873
 
                key: "showdelay", 
4874
 
                value: 200, 
4875
 
                validator: Lang.isNumber 
4876
 
            }, 
4877
 
 
4878
 
            "AUTO_DISMISS_DELAY": { 
4879
 
                key: "autodismissdelay", 
4880
 
                value: 5000, 
4881
 
                validator: Lang.isNumber 
4882
 
            }, 
4883
 
 
4884
 
            "HIDE_DELAY": { 
4885
 
                key: "hidedelay", 
4886
 
                value: 250, 
4887
 
                validator: Lang.isNumber 
4888
 
            }, 
4889
 
 
4890
 
            "TEXT": { 
4891
 
                key: "text", 
4892
 
                suppressEvent: true 
4893
 
            }, 
4894
 
 
4895
 
            "CONTAINER": { 
4896
 
                key: "container"
4897
 
            },
4898
 
 
4899
 
            "DISABLED": {
4900
 
                key: "disabled",
4901
 
                value: false,
4902
 
                suppressEvent: true
4903
 
            }
4904
 
        },
4905
 
 
4906
 
        /**
4907
 
        * Constant representing the name of the Tooltip's events
4908
 
        * @property EVENT_TYPES
4909
 
        * @private
4910
 
        * @final
4911
 
        * @type Object
4912
 
        */
4913
 
        EVENT_TYPES = {
4914
 
            "CONTEXT_MOUSE_OVER": "contextMouseOver",
4915
 
            "CONTEXT_MOUSE_OUT": "contextMouseOut",
4916
 
            "CONTEXT_TRIGGER": "contextTrigger"
4917
 
        };
4918
 
 
4919
 
    /**
4920
 
    * Constant representing the Tooltip CSS class
4921
 
    * @property YAHOO.widget.Tooltip.CSS_TOOLTIP
4922
 
    * @static
4923
 
    * @final
4924
 
    * @type String
4925
 
    */
4926
 
    Tooltip.CSS_TOOLTIP = "yui-tt";
4927
 
 
4928
 
    function restoreOriginalWidth(sOriginalWidth, sForcedWidth) {
4929
 
 
4930
 
        var oConfig = this.cfg,
4931
 
            sCurrentWidth = oConfig.getProperty("width");
4932
 
 
4933
 
        if (sCurrentWidth == sForcedWidth) {
4934
 
            oConfig.setProperty("width", sOriginalWidth);
4935
 
        }
4936
 
    }
4937
 
 
4938
 
    /* 
4939
 
        changeContent event handler that sets a Tooltip instance's "width"
4940
 
        configuration property to the value of its root HTML 
4941
 
        elements's offsetWidth if a specific width has not been set.
4942
 
    */
4943
 
 
4944
 
    function setWidthToOffsetWidth(p_sType, p_aArgs) {
4945
 
 
4946
 
        if ("_originalWidth" in this) {
4947
 
            restoreOriginalWidth.call(this, this._originalWidth, this._forcedWidth);
4948
 
        }
4949
 
 
4950
 
        var oBody = document.body,
4951
 
            oConfig = this.cfg,
4952
 
            sOriginalWidth = oConfig.getProperty("width"),
4953
 
            sNewWidth,
4954
 
            oClone;
4955
 
 
4956
 
        if ((!sOriginalWidth || sOriginalWidth == "auto") && 
4957
 
            (oConfig.getProperty("container") != oBody || 
4958
 
            oConfig.getProperty("x") >= Dom.getViewportWidth() || 
4959
 
            oConfig.getProperty("y") >= Dom.getViewportHeight())) {
4960
 
 
4961
 
            oClone = this.element.cloneNode(true);
4962
 
            oClone.style.visibility = "hidden";
4963
 
            oClone.style.top = "0px";
4964
 
            oClone.style.left = "0px";
4965
 
 
4966
 
            oBody.appendChild(oClone);
4967
 
 
4968
 
            sNewWidth = (oClone.offsetWidth + "px");
4969
 
 
4970
 
            oBody.removeChild(oClone);
4971
 
            oClone = null;
4972
 
 
4973
 
            oConfig.setProperty("width", sNewWidth);
4974
 
            oConfig.refireEvent("xy");
4975
 
 
4976
 
            this._originalWidth = sOriginalWidth || "";
4977
 
            this._forcedWidth = sNewWidth;
4978
 
        }
4979
 
    }
4980
 
 
4981
 
    // "onDOMReady" that renders the ToolTip
4982
 
 
4983
 
    function onDOMReady(p_sType, p_aArgs, p_oObject) {
4984
 
        this.render(p_oObject);
4985
 
    }
4986
 
 
4987
 
    //  "init" event handler that automatically renders the Tooltip
4988
 
 
4989
 
    function onInit() {
4990
 
        Event.onDOMReady(onDOMReady, this.cfg.getProperty("container"), this);
4991
 
    }
4992
 
 
4993
 
    YAHOO.extend(Tooltip, YAHOO.widget.Overlay, { 
4994
 
 
4995
 
        /**
4996
 
        * The Tooltip initialization method. This method is automatically 
4997
 
        * called by the constructor. A Tooltip is automatically rendered by 
4998
 
        * the init method, and it also is set to be invisible by default, 
4999
 
        * and constrained to viewport by default as well.
5000
 
        * @method init
5001
 
        * @param {String} el The element ID representing the Tooltip <em>OR</em>
5002
 
        * @param {HTMLElement} el The element representing the Tooltip
5003
 
        * @param {Object} userConfig The configuration object literal 
5004
 
        * containing the configuration that should be set for this Tooltip. 
5005
 
        * See configuration documentation for more details.
5006
 
        */
5007
 
        init: function (el, userConfig) {
5008
 
 
5009
 
            this.logger = new YAHOO.widget.LogWriter(this.toString());
5010
 
 
5011
 
            Tooltip.superclass.init.call(this, el);
5012
 
 
5013
 
            this.beforeInitEvent.fire(Tooltip);
5014
 
 
5015
 
            Dom.addClass(this.element, Tooltip.CSS_TOOLTIP);
5016
 
 
5017
 
            if (userConfig) {
5018
 
                this.cfg.applyConfig(userConfig, true);
5019
 
            }
5020
 
 
5021
 
            this.cfg.queueProperty("visible", false);
5022
 
            this.cfg.queueProperty("constraintoviewport", true);
5023
 
 
5024
 
            this.setBody("");
5025
 
 
5026
 
            this.subscribe("changeContent", setWidthToOffsetWidth);
5027
 
            this.subscribe("init", onInit);
5028
 
            this.subscribe("render", this.onRender);
5029
 
 
5030
 
            this.initEvent.fire(Tooltip);
5031
 
        },
5032
 
 
5033
 
        /**
5034
 
        * Initializes the custom events for Tooltip
5035
 
        * @method initEvents
5036
 
        */
5037
 
        initEvents: function () {
5038
 
 
5039
 
            Tooltip.superclass.initEvents.call(this);
5040
 
            var SIGNATURE = CustomEvent.LIST;
5041
 
 
5042
 
            /**
5043
 
            * CustomEvent fired when user mouses over a context element. Returning false from
5044
 
            * a subscriber to this event will prevent the tooltip from being displayed for
5045
 
            * the current context element.
5046
 
            * 
5047
 
            * @event contextMouseOverEvent
5048
 
            * @param {HTMLElement} context The context element which the user just moused over
5049
 
            * @param {DOMEvent} e The DOM event object, associated with the mouse over
5050
 
            */
5051
 
            this.contextMouseOverEvent = this.createEvent(EVENT_TYPES.CONTEXT_MOUSE_OVER);
5052
 
            this.contextMouseOverEvent.signature = SIGNATURE;
5053
 
 
5054
 
            /**
5055
 
            * CustomEvent fired when the user mouses out of a context element.
5056
 
            * 
5057
 
            * @event contextMouseOutEvent
5058
 
            * @param {HTMLElement} context The context element which the user just moused out of
5059
 
            * @param {DOMEvent} e The DOM event object, associated with the mouse out
5060
 
            */
5061
 
            this.contextMouseOutEvent = this.createEvent(EVENT_TYPES.CONTEXT_MOUSE_OUT);
5062
 
            this.contextMouseOutEvent.signature = SIGNATURE;
5063
 
 
5064
 
            /**
5065
 
            * CustomEvent fired just before the tooltip is displayed for the current context.
5066
 
            * <p>
5067
 
            *  You can subscribe to this event if you need to set up the text for the 
5068
 
            *  tooltip based on the context element for which it is about to be displayed.
5069
 
            * </p>
5070
 
            * <p>This event differs from the beforeShow event in following respects:</p>
5071
 
            * <ol>
5072
 
            *   <li>
5073
 
            *    When moving from one context element to another, if the tooltip is not
5074
 
            *    hidden (the <code>hidedelay</code> is not reached), the beforeShow and Show events will not
5075
 
            *    be fired when the tooltip is displayed for the new context since it is already visible.
5076
 
            *    However the contextTrigger event is always fired before displaying the tooltip for
5077
 
            *    a new context.
5078
 
            *   </li>
5079
 
            *   <li>
5080
 
            *    The trigger event provides access to the context element, allowing you to 
5081
 
            *    set the text of the tooltip based on context element for which the tooltip is
5082
 
            *    triggered.
5083
 
            *   </li>
5084
 
            * </ol>
5085
 
            * <p>
5086
 
            *  It is not possible to prevent the tooltip from being displayed
5087
 
            *  using this event. You can use the contextMouseOverEvent if you need to prevent
5088
 
            *  the tooltip from being displayed.
5089
 
            * </p>
5090
 
            * @event contextTriggerEvent
5091
 
            * @param {HTMLElement} context The context element for which the tooltip is triggered
5092
 
            */
5093
 
            this.contextTriggerEvent = this.createEvent(EVENT_TYPES.CONTEXT_TRIGGER);
5094
 
            this.contextTriggerEvent.signature = SIGNATURE;
5095
 
        },
5096
 
 
5097
 
        /**
5098
 
        * Initializes the class's configurable properties which can be 
5099
 
        * changed using the Overlay's Config object (cfg).
5100
 
        * @method initDefaultConfig
5101
 
        */
5102
 
        initDefaultConfig: function () {
5103
 
 
5104
 
            Tooltip.superclass.initDefaultConfig.call(this);
5105
 
 
5106
 
            /**
5107
 
            * Specifies whether the Tooltip should be kept from overlapping 
5108
 
            * its context element.
5109
 
            * @config preventoverlap
5110
 
            * @type Boolean
5111
 
            * @default true
5112
 
            */
5113
 
            this.cfg.addProperty(DEFAULT_CONFIG.PREVENT_OVERLAP.key, {
5114
 
                value: DEFAULT_CONFIG.PREVENT_OVERLAP.value, 
5115
 
                validator: DEFAULT_CONFIG.PREVENT_OVERLAP.validator, 
5116
 
                supercedes: DEFAULT_CONFIG.PREVENT_OVERLAP.supercedes
5117
 
            });
5118
 
 
5119
 
            /**
5120
 
            * The number of milliseconds to wait before showing a Tooltip 
5121
 
            * on mouseover.
5122
 
            * @config showdelay
5123
 
            * @type Number
5124
 
            * @default 200
5125
 
            */
5126
 
            this.cfg.addProperty(DEFAULT_CONFIG.SHOW_DELAY.key, {
5127
 
                handler: this.configShowDelay,
5128
 
                value: 200, 
5129
 
                validator: DEFAULT_CONFIG.SHOW_DELAY.validator
5130
 
            });
5131
 
 
5132
 
            /**
5133
 
            * The number of milliseconds to wait before automatically 
5134
 
            * dismissing a Tooltip after the mouse has been resting on the 
5135
 
            * context element.
5136
 
            * @config autodismissdelay
5137
 
            * @type Number
5138
 
            * @default 5000
5139
 
            */
5140
 
            this.cfg.addProperty(DEFAULT_CONFIG.AUTO_DISMISS_DELAY.key, {
5141
 
                handler: this.configAutoDismissDelay,
5142
 
                value: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.value,
5143
 
                validator: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.validator
5144
 
            });
5145
 
 
5146
 
            /**
5147
 
            * The number of milliseconds to wait before hiding a Tooltip 
5148
 
            * after mouseout.
5149
 
            * @config hidedelay
5150
 
            * @type Number
5151
 
            * @default 250
5152
 
            */
5153
 
            this.cfg.addProperty(DEFAULT_CONFIG.HIDE_DELAY.key, {
5154
 
                handler: this.configHideDelay,
5155
 
                value: DEFAULT_CONFIG.HIDE_DELAY.value, 
5156
 
                validator: DEFAULT_CONFIG.HIDE_DELAY.validator
5157
 
            });
5158
 
 
5159
 
            /**
5160
 
            * Specifies the Tooltip's text. 
5161
 
            * @config text
5162
 
            * @type String
5163
 
            * @default null
5164
 
            */
5165
 
            this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, {
5166
 
                handler: this.configText,
5167
 
                suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent
5168
 
            });
5169
 
 
5170
 
            /**
5171
 
            * Specifies the container element that the Tooltip's markup 
5172
 
            * should be rendered into.
5173
 
            * @config container
5174
 
            * @type HTMLElement/String
5175
 
            * @default document.body
5176
 
            */
5177
 
            this.cfg.addProperty(DEFAULT_CONFIG.CONTAINER.key, {
5178
 
                handler: this.configContainer,
5179
 
                value: document.body
5180
 
            });
5181
 
 
5182
 
            /**
5183
 
            * Specifies whether or not the tooltip is disabled. Disabled tooltips
5184
 
            * will not be displayed. If the tooltip is driven by the title attribute
5185
 
            * of the context element, the title attribute will still be removed for 
5186
 
            * disabled tooltips, to prevent default tooltip behavior.
5187
 
            * 
5188
 
            * @config disabled
5189
 
            * @type Boolean
5190
 
            * @default false
5191
 
            */
5192
 
            this.cfg.addProperty(DEFAULT_CONFIG.DISABLED.key, {
5193
 
                handler: this.configContainer,
5194
 
                value: DEFAULT_CONFIG.DISABLED.value,
5195
 
                supressEvent: DEFAULT_CONFIG.DISABLED.suppressEvent
5196
 
            });
5197
 
 
5198
 
            /**
5199
 
            * Specifies the element or elements that the Tooltip should be 
5200
 
            * anchored to on mouseover.
5201
 
            * @config context
5202
 
            * @type HTMLElement[]/String[]
5203
 
            * @default null
5204
 
            */ 
5205
 
 
5206
 
            /**
5207
 
            * String representing the width of the Tooltip.  <em>Please note:
5208
 
            * </em> As of version 2.3 if either no value or a value of "auto" 
5209
 
            * is specified, and the Toolip's "container" configuration property
5210
 
            * is set to something other than <code>document.body</code> or 
5211
 
            * its "context" element resides outside the immediately visible 
5212
 
            * portion of the document, the width of the Tooltip will be 
5213
 
            * calculated based on the offsetWidth of its root HTML and set just 
5214
 
            * before it is made visible.  The original value will be 
5215
 
            * restored when the Tooltip is hidden. This ensures the Tooltip is 
5216
 
            * rendered at a usable width.  For more information see 
5217
 
            * SourceForge bug #1685496 and SourceForge 
5218
 
            * bug #1735423.
5219
 
            * @config width
5220
 
            * @type String
5221
 
            * @default null
5222
 
            */
5223
 
        
5224
 
        },
5225
 
        
5226
 
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
5227
 
        
5228
 
        /**
5229
 
        * The default event handler fired when the "text" property is changed.
5230
 
        * @method configText
5231
 
        * @param {String} type The CustomEvent type (usually the property name)
5232
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
5233
 
        * handlers, args[0] will equal the newly applied value for the property.
5234
 
        * @param {Object} obj The scope object. For configuration handlers, 
5235
 
        * this will usually equal the owner.
5236
 
        */
5237
 
        configText: function (type, args, obj) {
5238
 
            var text = args[0];
5239
 
            if (text) {
5240
 
                this.setBody(text);
5241
 
            }
5242
 
        },
5243
 
        
5244
 
        /**
5245
 
        * The default event handler fired when the "container" property 
5246
 
        * is changed.
5247
 
        * @method configContainer
5248
 
        * @param {String} type The CustomEvent type (usually the property name)
5249
 
        * @param {Object[]} args The CustomEvent arguments. For 
5250
 
        * configuration handlers, args[0] will equal the newly applied value 
5251
 
        * for the property.
5252
 
        * @param {Object} obj The scope object. For configuration handlers,
5253
 
        * this will usually equal the owner.
5254
 
        */
5255
 
        configContainer: function (type, args, obj) {
5256
 
            var container = args[0];
5257
 
 
5258
 
            if (typeof container == 'string') {
5259
 
                this.cfg.setProperty("container", document.getElementById(container), true);
5260
 
            }
5261
 
        },
5262
 
        
5263
 
        /**
5264
 
        * @method _removeEventListeners
5265
 
        * @description Removes all of the DOM event handlers from the HTML
5266
 
        *  element(s) that trigger the display of the tooltip.
5267
 
        * @protected
5268
 
        */
5269
 
        _removeEventListeners: function () {
5270
 
        
5271
 
            var aElements = this._context,
5272
 
                nElements,
5273
 
                oElement,
5274
 
                i;
5275
 
 
5276
 
            if (aElements) {
5277
 
                nElements = aElements.length;
5278
 
                if (nElements > 0) {
5279
 
                    i = nElements - 1;
5280
 
                    do {
5281
 
                        oElement = aElements[i];
5282
 
                        Event.removeListener(oElement, "mouseover", this.onContextMouseOver);
5283
 
                        Event.removeListener(oElement, "mousemove", this.onContextMouseMove);
5284
 
                        Event.removeListener(oElement, "mouseout", this.onContextMouseOut);
5285
 
                    }
5286
 
                    while (i--);
5287
 
                }
5288
 
            }
5289
 
        },
5290
 
        
5291
 
        /**
5292
 
        * The default event handler fired when the "context" property 
5293
 
        * is changed.
5294
 
        * @method configContext
5295
 
        * @param {String} type The CustomEvent type (usually the property name)
5296
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
5297
 
        * handlers, args[0] will equal the newly applied value for the property.
5298
 
        * @param {Object} obj The scope object. For configuration handlers,
5299
 
        * this will usually equal the owner.
5300
 
        */
5301
 
        configContext: function (type, args, obj) {
5302
 
 
5303
 
            var context = args[0],
5304
 
                aElements,
5305
 
                nElements,
5306
 
                oElement,
5307
 
                i;
5308
 
 
5309
 
            if (context) {
5310
 
 
5311
 
                // Normalize parameter into an array
5312
 
                if (! (context instanceof Array)) {
5313
 
                    if (typeof context == "string") {
5314
 
                        this.cfg.setProperty("context", [document.getElementById(context)], true);
5315
 
                    } else { // Assuming this is an element
5316
 
                        this.cfg.setProperty("context", [context], true);
5317
 
                    }
5318
 
                    context = this.cfg.getProperty("context");
5319
 
                }
5320
 
 
5321
 
                // Remove any existing mouseover/mouseout listeners
5322
 
                this._removeEventListeners();
5323
 
 
5324
 
                // Add mouseover/mouseout listeners to context elements
5325
 
                this._context = context;
5326
 
 
5327
 
                aElements = this._context;
5328
 
 
5329
 
                if (aElements) {
5330
 
                    nElements = aElements.length;
5331
 
                    if (nElements > 0) {
5332
 
                        i = nElements - 1;
5333
 
                        do {
5334
 
                            oElement = aElements[i];
5335
 
                            Event.on(oElement, "mouseover", this.onContextMouseOver, this);
5336
 
                            Event.on(oElement, "mousemove", this.onContextMouseMove, this);
5337
 
                            Event.on(oElement, "mouseout", this.onContextMouseOut, this);
5338
 
                        }
5339
 
                        while (i--);
5340
 
                    }
5341
 
                }
5342
 
            }
5343
 
        },
5344
 
 
5345
 
        // END BUILT-IN PROPERTY EVENT HANDLERS //
5346
 
 
5347
 
        // BEGIN BUILT-IN DOM EVENT HANDLERS //
5348
 
 
5349
 
        /**
5350
 
        * The default event handler fired when the user moves the mouse while 
5351
 
        * over the context element.
5352
 
        * @method onContextMouseMove
5353
 
        * @param {DOMEvent} e The current DOM event
5354
 
        * @param {Object} obj The object argument
5355
 
        */
5356
 
        onContextMouseMove: function (e, obj) {
5357
 
            obj.pageX = Event.getPageX(e);
5358
 
            obj.pageY = Event.getPageY(e);
5359
 
        },
5360
 
 
5361
 
        /**
5362
 
        * The default event handler fired when the user mouses over the 
5363
 
        * context element.
5364
 
        * @method onContextMouseOver
5365
 
        * @param {DOMEvent} e The current DOM event
5366
 
        * @param {Object} obj The object argument
5367
 
        */
5368
 
        onContextMouseOver: function (e, obj) {
5369
 
            var context = this;
5370
 
 
5371
 
            if (context.title) {
5372
 
                obj._tempTitle = context.title;
5373
 
                context.title = "";
5374
 
            }
5375
 
 
5376
 
            // Fire first, to honor disabled set in the listner
5377
 
            if (obj.fireEvent("contextMouseOver", context, e) !== false 
5378
 
                    && !obj.cfg.getProperty("disabled")) {
5379
 
 
5380
 
                // Stop the tooltip from being hidden (set on last mouseout)
5381
 
                if (obj.hideProcId) {
5382
 
                    clearTimeout(obj.hideProcId);
5383
 
                    obj.logger.log("Clearing hide timer: " + obj.hideProcId, "time");
5384
 
                    obj.hideProcId = null;
5385
 
                }
5386
 
 
5387
 
                Event.on(context, "mousemove", obj.onContextMouseMove, obj);
5388
 
 
5389
 
                /**
5390
 
                * The unique process ID associated with the thread responsible 
5391
 
                * for showing the Tooltip.
5392
 
                * @type int
5393
 
                */
5394
 
                obj.showProcId = obj.doShow(e, context);
5395
 
                obj.logger.log("Setting show tooltip timeout: " + obj.showProcId, "time");
5396
 
            }
5397
 
        },
5398
 
 
5399
 
        /**
5400
 
        * The default event handler fired when the user mouses out of 
5401
 
        * the context element.
5402
 
        * @method onContextMouseOut
5403
 
        * @param {DOMEvent} e The current DOM event
5404
 
        * @param {Object} obj The object argument
5405
 
        */
5406
 
        onContextMouseOut: function (e, obj) {
5407
 
            var el = this;
5408
 
 
5409
 
            if (obj._tempTitle) {
5410
 
                el.title = obj._tempTitle;
5411
 
                obj._tempTitle = null;
5412
 
            }
5413
 
 
5414
 
            if (obj.showProcId) {
5415
 
                clearTimeout(obj.showProcId);
5416
 
                obj.logger.log("Clearing show timer: " + obj.showProcId, "time");
5417
 
                obj.showProcId = null;
5418
 
            }
5419
 
 
5420
 
            if (obj.hideProcId) {
5421
 
                clearTimeout(obj.hideProcId);
5422
 
                obj.logger.log("Clearing hide timer: " + obj.hideProcId, "time");
5423
 
                obj.hideProcId = null;
5424
 
            }
5425
 
 
5426
 
            obj.fireEvent("contextMouseOut", el, e);
5427
 
 
5428
 
            obj.hideProcId = setTimeout(function () {
5429
 
                obj.hide();
5430
 
            }, obj.cfg.getProperty("hidedelay"));
5431
 
        },
5432
 
 
5433
 
        // END BUILT-IN DOM EVENT HANDLERS //
5434
 
 
5435
 
        /**
5436
 
        * Processes the showing of the Tooltip by setting the timeout delay 
5437
 
        * and offset of the Tooltip.
5438
 
        * @method doShow
5439
 
        * @param {DOMEvent} e The current DOM event
5440
 
        * @param {HTMLElement} context The current context element
5441
 
        * @return {Number} The process ID of the timeout function associated 
5442
 
        * with doShow
5443
 
        */
5444
 
        doShow: function (e, context) {
5445
 
 
5446
 
            var yOffset = 25,
5447
 
                me = this;
5448
 
 
5449
 
            if (UA.opera && context.tagName && 
5450
 
                context.tagName.toUpperCase() == "A") {
5451
 
                yOffset += 12;
5452
 
            }
5453
 
 
5454
 
            return setTimeout(function () {
5455
 
 
5456
 
                var txt = me.cfg.getProperty("text");
5457
 
 
5458
 
                // title does not over-ride text
5459
 
                if (me._tempTitle && (txt === "" || YAHOO.lang.isUndefined(txt) || YAHOO.lang.isNull(txt))) {
5460
 
                    me.setBody(me._tempTitle);
5461
 
                } else {
5462
 
                    me.cfg.refireEvent("text");
5463
 
                }
5464
 
 
5465
 
                me.logger.log("Show tooltip", "time");
5466
 
                me.moveTo(me.pageX, me.pageY + yOffset);
5467
 
 
5468
 
                if (me.cfg.getProperty("preventoverlap")) {
5469
 
                    me.preventOverlap(me.pageX, me.pageY);
5470
 
                }
5471
 
 
5472
 
                Event.removeListener(context, "mousemove", me.onContextMouseMove);
5473
 
 
5474
 
                me.contextTriggerEvent.fire(context);
5475
 
 
5476
 
                me.show();
5477
 
 
5478
 
                me.hideProcId = me.doHide();
5479
 
                me.logger.log("Hide tooltip time active: " + me.hideProcId, "time");
5480
 
 
5481
 
            }, this.cfg.getProperty("showdelay"));
5482
 
        },
5483
 
 
5484
 
        /**
5485
 
        * Sets the timeout for the auto-dismiss delay, which by default is 5 
5486
 
        * seconds, meaning that a tooltip will automatically dismiss itself 
5487
 
        * after 5 seconds of being displayed.
5488
 
        * @method doHide
5489
 
        */
5490
 
        doHide: function () {
5491
 
 
5492
 
            var me = this;
5493
 
 
5494
 
            me.logger.log("Setting hide tooltip timeout", "time");
5495
 
 
5496
 
            return setTimeout(function () {
5497
 
 
5498
 
                me.logger.log("Hide tooltip", "time");
5499
 
                me.hide();
5500
 
 
5501
 
            }, this.cfg.getProperty("autodismissdelay"));
5502
 
 
5503
 
        },
5504
 
 
5505
 
        /**
5506
 
        * Fired when the Tooltip is moved, this event handler is used to 
5507
 
        * prevent the Tooltip from overlapping with its context element.
5508
 
        * @method preventOverlay
5509
 
        * @param {Number} pageX The x coordinate position of the mouse pointer
5510
 
        * @param {Number} pageY The y coordinate position of the mouse pointer
5511
 
        */
5512
 
        preventOverlap: function (pageX, pageY) {
5513
 
        
5514
 
            var height = this.element.offsetHeight,
5515
 
                mousePoint = new YAHOO.util.Point(pageX, pageY),
5516
 
                elementRegion = Dom.getRegion(this.element);
5517
 
        
5518
 
            elementRegion.top -= 5;
5519
 
            elementRegion.left -= 5;
5520
 
            elementRegion.right += 5;
5521
 
            elementRegion.bottom += 5;
5522
 
        
5523
 
            this.logger.log("context " + elementRegion, "ttip");
5524
 
            this.logger.log("mouse " + mousePoint, "ttip");
5525
 
        
5526
 
            if (elementRegion.contains(mousePoint)) {
5527
 
                this.logger.log("OVERLAP", "warn");
5528
 
                this.cfg.setProperty("y", (pageY - height - 5));
5529
 
            }
5530
 
        },
5531
 
 
5532
 
 
5533
 
        /**
5534
 
        * @method onRender
5535
 
        * @description "render" event handler for the Tooltip.
5536
 
        * @param {String} p_sType String representing the name of the event  
5537
 
        * that was fired.
5538
 
        * @param {Array} p_aArgs Array of arguments sent when the event 
5539
 
        * was fired.
5540
 
        */
5541
 
        onRender: function (p_sType, p_aArgs) {
5542
 
    
5543
 
            function sizeShadow() {
5544
 
    
5545
 
                var oElement = this.element,
5546
 
                    oShadow = this.underlay;
5547
 
            
5548
 
                if (oShadow) {
5549
 
                    oShadow.style.width = (oElement.offsetWidth + 6) + "px";
5550
 
                    oShadow.style.height = (oElement.offsetHeight + 1) + "px"; 
5551
 
                }
5552
 
            
5553
 
            }
5554
 
 
5555
 
            function addShadowVisibleClass() {
5556
 
                Dom.addClass(this.underlay, "yui-tt-shadow-visible");
5557
 
 
5558
 
                if (UA.ie) {
5559
 
                    this.forceUnderlayRedraw();
5560
 
                }
5561
 
            }
5562
 
 
5563
 
            function removeShadowVisibleClass() {
5564
 
                Dom.removeClass(this.underlay, "yui-tt-shadow-visible");
5565
 
            }
5566
 
 
5567
 
            function createShadow() {
5568
 
    
5569
 
                var oShadow = this.underlay,
5570
 
                    oElement,
5571
 
                    Module,
5572
 
                    nIE,
5573
 
                    me;
5574
 
    
5575
 
                if (!oShadow) {
5576
 
    
5577
 
                    oElement = this.element;
5578
 
                    Module = YAHOO.widget.Module;
5579
 
                    nIE = UA.ie;
5580
 
                    me = this;
5581
 
 
5582
 
                    if (!m_oShadowTemplate) {
5583
 
                        m_oShadowTemplate = document.createElement("div");
5584
 
                        m_oShadowTemplate.className = "yui-tt-shadow";
5585
 
                    }
5586
 
 
5587
 
                    oShadow = m_oShadowTemplate.cloneNode(false);
5588
 
 
5589
 
                    oElement.appendChild(oShadow);
5590
 
 
5591
 
                    this.underlay = oShadow;
5592
 
 
5593
 
                    // Backward compatibility, even though it's probably 
5594
 
                    // intended to be "private", it isn't marked as such in the api docs
5595
 
                    this._shadow = this.underlay;
5596
 
 
5597
 
                    addShadowVisibleClass.call(this);
5598
 
 
5599
 
                    this.subscribe("beforeShow", addShadowVisibleClass);
5600
 
                    this.subscribe("hide", removeShadowVisibleClass);
5601
 
 
5602
 
                    if (bIEQuirks) {
5603
 
                        window.setTimeout(function () { 
5604
 
                            sizeShadow.call(me); 
5605
 
                        }, 0);
5606
 
    
5607
 
                        this.cfg.subscribeToConfigEvent("width", sizeShadow);
5608
 
                        this.cfg.subscribeToConfigEvent("height", sizeShadow);
5609
 
                        this.subscribe("changeContent", sizeShadow);
5610
 
 
5611
 
                        Module.textResizeEvent.subscribe(sizeShadow, this, true);
5612
 
                        this.subscribe("destroy", function () {
5613
 
                            Module.textResizeEvent.unsubscribe(sizeShadow, this);
5614
 
                        });
5615
 
                    }
5616
 
                }
5617
 
            }
5618
 
 
5619
 
            function onBeforeShow() {
5620
 
                createShadow.call(this);
5621
 
                this.unsubscribe("beforeShow", onBeforeShow);
5622
 
            }
5623
 
 
5624
 
            if (this.cfg.getProperty("visible")) {
5625
 
                createShadow.call(this);
5626
 
            } else {
5627
 
                this.subscribe("beforeShow", onBeforeShow);
5628
 
            }
5629
 
        
5630
 
        },
5631
 
 
5632
 
        /**
5633
 
         * Forces the underlay element to be repainted, through the application/removal
5634
 
         * of a yui-force-redraw class to the underlay element.
5635
 
         * 
5636
 
         * @method forceUnderlayRedraw
5637
 
         */
5638
 
        forceUnderlayRedraw : function() {
5639
 
            var tt = this;
5640
 
            Dom.addClass(tt.underlay, "yui-force-redraw");
5641
 
            setTimeout(function() {Dom.removeClass(tt.underlay, "yui-force-redraw");}, 0);
5642
 
        },
5643
 
 
5644
 
        /**
5645
 
        * Removes the Tooltip element from the DOM and sets all child 
5646
 
        * elements to null.
5647
 
        * @method destroy
5648
 
        */
5649
 
        destroy: function () {
5650
 
        
5651
 
            // Remove any existing mouseover/mouseout listeners
5652
 
            this._removeEventListeners();
5653
 
 
5654
 
            Tooltip.superclass.destroy.call(this);  
5655
 
        
5656
 
        },
5657
 
        
5658
 
        /**
5659
 
        * Returns a string representation of the object.
5660
 
        * @method toString
5661
 
        * @return {String} The string representation of the Tooltip
5662
 
        */
5663
 
        toString: function () {
5664
 
            return "Tooltip " + this.id;
5665
 
        }
5666
 
    
5667
 
    });
5668
 
 
5669
 
}());
5670
 
 
5671
 
(function () {
5672
 
 
5673
 
    /**
5674
 
    * Panel is an implementation of Overlay that behaves like an OS window, 
5675
 
    * with a draggable header and an optional close icon at the top right.
5676
 
    * @namespace YAHOO.widget
5677
 
    * @class Panel
5678
 
    * @extends YAHOO.widget.Overlay
5679
 
    * @constructor
5680
 
    * @param {String} el The element ID representing the Panel <em>OR</em>
5681
 
    * @param {HTMLElement} el The element representing the Panel
5682
 
    * @param {Object} userConfig The configuration object literal containing 
5683
 
    * the configuration that should be set for this Panel. See configuration 
5684
 
    * documentation for more details.
5685
 
    */
5686
 
    YAHOO.widget.Panel = function (el, userConfig) {
5687
 
        YAHOO.widget.Panel.superclass.constructor.call(this, el, userConfig);
5688
 
    };
5689
 
 
5690
 
    var _currentModal = null;
5691
 
 
5692
 
    var Lang = YAHOO.lang,
5693
 
        Util = YAHOO.util,
5694
 
        Dom = Util.Dom,
5695
 
        Event = Util.Event,
5696
 
        CustomEvent = Util.CustomEvent,
5697
 
        KeyListener = YAHOO.util.KeyListener,
5698
 
        Config = Util.Config,
5699
 
        Overlay = YAHOO.widget.Overlay,
5700
 
        Panel = YAHOO.widget.Panel,
5701
 
        UA = YAHOO.env.ua,
5702
 
 
5703
 
        bIEQuirks = (UA.ie && (UA.ie <= 6 || document.compatMode == "BackCompat")),
5704
 
 
5705
 
        m_oMaskTemplate,
5706
 
        m_oUnderlayTemplate,
5707
 
        m_oCloseIconTemplate,
5708
 
 
5709
 
        /**
5710
 
        * Constant representing the name of the Panel's events
5711
 
        * @property EVENT_TYPES
5712
 
        * @private
5713
 
        * @final
5714
 
        * @type Object
5715
 
        */
5716
 
        EVENT_TYPES = {
5717
 
            "SHOW_MASK": "showMask",
5718
 
            "HIDE_MASK": "hideMask",
5719
 
            "DRAG": "drag"
5720
 
        },
5721
 
 
5722
 
        /**
5723
 
        * Constant representing the Panel's configuration properties
5724
 
        * @property DEFAULT_CONFIG
5725
 
        * @private
5726
 
        * @final
5727
 
        * @type Object
5728
 
        */
5729
 
        DEFAULT_CONFIG = {
5730
 
 
5731
 
            "CLOSE": { 
5732
 
                key: "close", 
5733
 
                value: true, 
5734
 
                validator: Lang.isBoolean, 
5735
 
                supercedes: ["visible"] 
5736
 
            },
5737
 
 
5738
 
            "DRAGGABLE": {
5739
 
                key: "draggable", 
5740
 
                value: (Util.DD ? true : false), 
5741
 
                validator: Lang.isBoolean, 
5742
 
                supercedes: ["visible"]  
5743
 
            },
5744
 
 
5745
 
            "DRAG_ONLY" : {
5746
 
                key: "dragonly",
5747
 
                value: false,
5748
 
                validator: Lang.isBoolean,
5749
 
                supercedes: ["draggable"]
5750
 
            },
5751
 
 
5752
 
            "UNDERLAY": { 
5753
 
                key: "underlay", 
5754
 
                value: "shadow", 
5755
 
                supercedes: ["visible"] 
5756
 
            },
5757
 
 
5758
 
            "MODAL": { 
5759
 
                key: "modal", 
5760
 
                value: false, 
5761
 
                validator: Lang.isBoolean, 
5762
 
                supercedes: ["visible", "zindex"]
5763
 
            },
5764
 
 
5765
 
            "KEY_LISTENERS": {
5766
 
                key: "keylisteners",
5767
 
                suppressEvent: true,
5768
 
                supercedes: ["visible"]
5769
 
            },
5770
 
 
5771
 
            "STRINGS" : {
5772
 
                key: "strings",
5773
 
                supercedes: ["close"],
5774
 
                validator: Lang.isObject,
5775
 
                value: {
5776
 
                    close: "Close"
5777
 
                }
5778
 
            }
5779
 
        };
5780
 
 
5781
 
    /**
5782
 
    * Constant representing the default CSS class used for a Panel
5783
 
    * @property YAHOO.widget.Panel.CSS_PANEL
5784
 
    * @static
5785
 
    * @final
5786
 
    * @type String
5787
 
    */
5788
 
    Panel.CSS_PANEL = "yui-panel";
5789
 
    
5790
 
    /**
5791
 
    * Constant representing the default CSS class used for a Panel's 
5792
 
    * wrapping container
5793
 
    * @property YAHOO.widget.Panel.CSS_PANEL_CONTAINER
5794
 
    * @static
5795
 
    * @final
5796
 
    * @type String
5797
 
    */
5798
 
    Panel.CSS_PANEL_CONTAINER = "yui-panel-container";
5799
 
 
5800
 
    /**
5801
 
     * Constant representing the default set of focusable elements 
5802
 
     * on the pagewhich Modal Panels will prevent access to, when
5803
 
     * the modal mask is displayed
5804
 
     * 
5805
 
     * @property YAHOO.widget.Panel.FOCUSABLE
5806
 
     * @static
5807
 
     * @type Array
5808
 
     */
5809
 
    Panel.FOCUSABLE = [
5810
 
        "a",
5811
 
        "button",
5812
 
        "select",
5813
 
        "textarea",
5814
 
        "input",
5815
 
        "iframe"
5816
 
    ];
5817
 
 
5818
 
    // Private CustomEvent listeners
5819
 
 
5820
 
    /* 
5821
 
        "beforeRender" event handler that creates an empty header for a Panel 
5822
 
        instance if its "draggable" configuration property is set to "true" 
5823
 
        and no header has been created.
5824
 
    */
5825
 
 
5826
 
    function createHeader(p_sType, p_aArgs) {
5827
 
        if (!this.header && this.cfg.getProperty("draggable")) {
5828
 
            this.setHeader("&#160;");
5829
 
        }
5830
 
    }
5831
 
 
5832
 
    /* 
5833
 
        "hide" event handler that sets a Panel instance's "width"
5834
 
        configuration property back to its original value before 
5835
 
        "setWidthToOffsetWidth" was called.
5836
 
    */
5837
 
    
5838
 
    function restoreOriginalWidth(p_sType, p_aArgs, p_oObject) {
5839
 
 
5840
 
        var sOriginalWidth = p_oObject[0],
5841
 
            sNewWidth = p_oObject[1],
5842
 
            oConfig = this.cfg,
5843
 
            sCurrentWidth = oConfig.getProperty("width");
5844
 
 
5845
 
        if (sCurrentWidth == sNewWidth) {
5846
 
            oConfig.setProperty("width", sOriginalWidth);
5847
 
        }
5848
 
 
5849
 
        this.unsubscribe("hide", restoreOriginalWidth, p_oObject);
5850
 
    }
5851
 
 
5852
 
    /* 
5853
 
        "beforeShow" event handler that sets a Panel instance's "width"
5854
 
        configuration property to the value of its root HTML 
5855
 
        elements's offsetWidth
5856
 
    */
5857
 
 
5858
 
    function setWidthToOffsetWidth(p_sType, p_aArgs) {
5859
 
 
5860
 
        var oConfig,
5861
 
            sOriginalWidth,
5862
 
            sNewWidth;
5863
 
 
5864
 
        if (bIEQuirks) {
5865
 
 
5866
 
            oConfig = this.cfg;
5867
 
            sOriginalWidth = oConfig.getProperty("width");
5868
 
            
5869
 
            if (!sOriginalWidth || sOriginalWidth == "auto") {
5870
 
    
5871
 
                sNewWidth = (this.element.offsetWidth + "px");
5872
 
    
5873
 
                oConfig.setProperty("width", sNewWidth);
5874
 
 
5875
 
                this.subscribe("hide", restoreOriginalWidth, 
5876
 
                    [(sOriginalWidth || ""), sNewWidth]);
5877
 
            
5878
 
            }
5879
 
        }
5880
 
    }
5881
 
 
5882
 
    YAHOO.extend(Panel, Overlay, {
5883
 
 
5884
 
        /**
5885
 
        * The Overlay initialization method, which is executed for Overlay and 
5886
 
        * all of its subclasses. This method is automatically called by the 
5887
 
        * constructor, and  sets up all DOM references for pre-existing markup, 
5888
 
        * and creates required markup if it is not already present.
5889
 
        * @method init
5890
 
        * @param {String} el The element ID representing the Overlay <em>OR</em>
5891
 
        * @param {HTMLElement} el The element representing the Overlay
5892
 
        * @param {Object} userConfig The configuration object literal 
5893
 
        * containing the configuration that should be set for this Overlay. 
5894
 
        * See configuration documentation for more details.
5895
 
        */
5896
 
        init: function (el, userConfig) {
5897
 
            /*
5898
 
                 Note that we don't pass the user config in here yet because 
5899
 
                 we only want it executed once, at the lowest subclass level
5900
 
            */
5901
 
 
5902
 
            Panel.superclass.init.call(this, el/*, userConfig*/);
5903
 
 
5904
 
            this.beforeInitEvent.fire(Panel);
5905
 
 
5906
 
            Dom.addClass(this.element, Panel.CSS_PANEL);
5907
 
 
5908
 
            this.buildWrapper();
5909
 
 
5910
 
            if (userConfig) {
5911
 
                this.cfg.applyConfig(userConfig, true);
5912
 
            }
5913
 
 
5914
 
            this.subscribe("showMask", this._addFocusHandlers);
5915
 
            this.subscribe("hideMask", this._removeFocusHandlers);
5916
 
            this.subscribe("beforeRender", createHeader);
5917
 
 
5918
 
            this.subscribe("render", function() {
5919
 
                this.setFirstLastFocusable();
5920
 
                this.subscribe("changeContent", this.setFirstLastFocusable);
5921
 
            });
5922
 
 
5923
 
            this.subscribe("show", this.focusFirst);
5924
 
 
5925
 
            this.initEvent.fire(Panel);
5926
 
        },
5927
 
 
5928
 
        /**
5929
 
         * @method _onElementFocus
5930
 
         * @private
5931
 
         *
5932
 
         * "focus" event handler for a focuable element. Used to automatically
5933
 
         * blur the element when it receives focus to ensure that a Panel
5934
 
         * instance's modality is not compromised.
5935
 
         *
5936
 
         * @param {Event} e The DOM event object
5937
 
         */
5938
 
        _onElementFocus : function(e){
5939
 
 
5940
 
            if(_currentModal === this) {
5941
 
 
5942
 
                var target = Event.getTarget(e),
5943
 
                    doc = document.documentElement,
5944
 
                    insideDoc = (target !== doc && target !== window);
5945
 
 
5946
 
                // mask and documentElement checks added for IE, which focuses on the mask when it's clicked on, and focuses on 
5947
 
                // the documentElement, when the document scrollbars are clicked on
5948
 
                if (insideDoc && target !== this.element && target !== this.mask && !Dom.isAncestor(this.element, target)) {
5949
 
                    try {
5950
 
                        if (this.firstElement) {
5951
 
                            this.firstElement.focus();
5952
 
                        } else {
5953
 
                            if (this._modalFocus) {
5954
 
                                this._modalFocus.focus();
5955
 
                            } else {
5956
 
                                this.innerElement.focus();
5957
 
                            }
5958
 
                        }
5959
 
                    } catch(err){
5960
 
                        // Just in case we fail to focus
5961
 
                        try {
5962
 
                            if (insideDoc && target !== document.body) {
5963
 
                                target.blur();
5964
 
                            }
5965
 
                        } catch(err2) { }
5966
 
                    }
5967
 
                }
5968
 
            }
5969
 
        },
5970
 
 
5971
 
        /** 
5972
 
         *  @method _addFocusHandlers
5973
 
         *  @protected
5974
 
         *  
5975
 
         *  "showMask" event handler that adds a "focus" event handler to all
5976
 
         *  focusable elements in the document to enforce a Panel instance's 
5977
 
         *  modality from being compromised.
5978
 
         *
5979
 
         *  @param p_sType {String} Custom event type
5980
 
         *  @param p_aArgs {Array} Custom event arguments
5981
 
         */
5982
 
        _addFocusHandlers: function(p_sType, p_aArgs) {
5983
 
            if (!this.firstElement) {
5984
 
                if (UA.webkit || UA.opera) {
5985
 
                    if (!this._modalFocus) {
5986
 
                        this._createHiddenFocusElement();
5987
 
                    }
5988
 
                } else {
5989
 
                    this.innerElement.tabIndex = 0;
5990
 
                }
5991
 
            }
5992
 
            this.setTabLoop(this.firstElement, this.lastElement);
5993
 
            Event.onFocus(document.documentElement, this._onElementFocus, this, true);
5994
 
            _currentModal = this;
5995
 
        },
5996
 
 
5997
 
        /**
5998
 
         * Creates a hidden focusable element, used to focus on,
5999
 
         * to enforce modality for browsers in which focus cannot
6000
 
         * be applied to the container box.
6001
 
         * 
6002
 
         * @method _createHiddenFocusElement
6003
 
         * @private
6004
 
         */
6005
 
        _createHiddenFocusElement : function() {
6006
 
            var e = document.createElement("button");
6007
 
            e.style.height = "1px";
6008
 
            e.style.width = "1px";
6009
 
            e.style.position = "absolute";
6010
 
            e.style.left = "-10000em";
6011
 
            e.style.opacity = 0;
6012
 
            e.tabIndex = -1;
6013
 
            this.innerElement.appendChild(e);
6014
 
            this._modalFocus = e;
6015
 
        },
6016
 
 
6017
 
        /**
6018
 
         *  @method _removeFocusHandlers
6019
 
         *  @protected
6020
 
         *
6021
 
         *  "hideMask" event handler that removes all "focus" event handlers added 
6022
 
         *  by the "addFocusEventHandlers" method.
6023
 
         *
6024
 
         *  @param p_sType {String} Event type
6025
 
         *  @param p_aArgs {Array} Event Arguments
6026
 
         */
6027
 
        _removeFocusHandlers: function(p_sType, p_aArgs) {
6028
 
            Event.removeFocusListener(document.documentElement, this._onElementFocus, this);
6029
 
 
6030
 
            if (_currentModal == this) {
6031
 
                _currentModal = null;
6032
 
            }
6033
 
        },
6034
 
 
6035
 
        /**
6036
 
         * Sets focus to the first element in the Panel.
6037
 
         *
6038
 
         * @method focusFirst
6039
 
         */
6040
 
        focusFirst: function (type, args, obj) {
6041
 
            var el = this.firstElement;
6042
 
 
6043
 
            if (args && args[1]) {
6044
 
                Event.stopEvent(args[1]);
6045
 
            }
6046
 
 
6047
 
            if (el) {
6048
 
                try {
6049
 
                    el.focus();
6050
 
                } catch(err) {
6051
 
                    // Ignore
6052
 
                }
6053
 
            }
6054
 
        },
6055
 
 
6056
 
        /**
6057
 
         * Sets focus to the last element in the Panel.
6058
 
         *
6059
 
         * @method focusLast
6060
 
         */
6061
 
        focusLast: function (type, args, obj) {
6062
 
            var el = this.lastElement;
6063
 
 
6064
 
            if (args && args[1]) {
6065
 
                Event.stopEvent(args[1]);
6066
 
            }
6067
 
 
6068
 
            if (el) {
6069
 
                try {
6070
 
                    el.focus();
6071
 
                } catch(err) {
6072
 
                    // Ignore
6073
 
                }
6074
 
            }
6075
 
        },
6076
 
 
6077
 
        /**
6078
 
         * Sets up a tab, shift-tab loop between the first and last elements
6079
 
         * provided. NOTE: Sets up the preventBackTab and preventTabOut KeyListener
6080
 
         * instance properties, which are reset everytime this method is invoked.
6081
 
         *
6082
 
         * @method setTabLoop
6083
 
         * @param {HTMLElement} firstElement
6084
 
         * @param {HTMLElement} lastElement
6085
 
         *
6086
 
         */
6087
 
        setTabLoop : function(firstElement, lastElement) {
6088
 
 
6089
 
            var backTab = this.preventBackTab, tab = this.preventTabOut,
6090
 
                showEvent = this.showEvent, hideEvent = this.hideEvent;
6091
 
 
6092
 
            if (backTab) {
6093
 
                backTab.disable();
6094
 
                showEvent.unsubscribe(backTab.enable, backTab);
6095
 
                hideEvent.unsubscribe(backTab.disable, backTab);
6096
 
                backTab = this.preventBackTab = null;
6097
 
            }
6098
 
 
6099
 
            if (tab) {
6100
 
                tab.disable();
6101
 
                showEvent.unsubscribe(tab.enable, tab);
6102
 
                hideEvent.unsubscribe(tab.disable,tab);
6103
 
                tab = this.preventTabOut = null;
6104
 
            }
6105
 
 
6106
 
            if (firstElement) {
6107
 
                this.preventBackTab = new KeyListener(firstElement, 
6108
 
                    {shift:true, keys:9},
6109
 
                    {fn:this.focusLast, scope:this, correctScope:true}
6110
 
                );
6111
 
                backTab = this.preventBackTab;
6112
 
 
6113
 
                showEvent.subscribe(backTab.enable, backTab, true);
6114
 
                hideEvent.subscribe(backTab.disable,backTab, true);
6115
 
            }
6116
 
 
6117
 
            if (lastElement) {
6118
 
                this.preventTabOut = new KeyListener(lastElement, 
6119
 
                    {shift:false, keys:9}, 
6120
 
                    {fn:this.focusFirst, scope:this, correctScope:true}
6121
 
                );
6122
 
                tab = this.preventTabOut;
6123
 
 
6124
 
                showEvent.subscribe(tab.enable, tab, true);
6125
 
                hideEvent.subscribe(tab.disable,tab, true);
6126
 
            }
6127
 
        },
6128
 
 
6129
 
        /**
6130
 
         * Returns an array of the currently focusable items which reside within
6131
 
         * Panel. The set of focusable elements the method looks for are defined
6132
 
         * in the Panel.FOCUSABLE static property
6133
 
         *
6134
 
         * @method getFocusableElements
6135
 
         * @param {HTMLElement} root element to start from.
6136
 
         */
6137
 
        getFocusableElements : function(root) {
6138
 
 
6139
 
            root = root || this.innerElement;
6140
 
 
6141
 
            var focusable = {};
6142
 
            for (var i = 0; i < Panel.FOCUSABLE.length; i++) {
6143
 
                focusable[Panel.FOCUSABLE[i]] = true;
6144
 
            }
6145
 
 
6146
 
            function isFocusable(el) {
6147
 
                if (el.focus && el.type !== "hidden" && !el.disabled && focusable[el.tagName.toLowerCase()]) {
6148
 
                    return true;
6149
 
                }
6150
 
                return false;
6151
 
            }
6152
 
 
6153
 
            // Not looking by Tag, since we want elements in DOM order
6154
 
            return Dom.getElementsBy(isFocusable, null, root);
6155
 
        },
6156
 
 
6157
 
        /**
6158
 
         * Sets the firstElement and lastElement instance properties
6159
 
         * to the first and last focusable elements in the Panel.
6160
 
         *
6161
 
         * @method setFirstLastFocusable
6162
 
         */
6163
 
        setFirstLastFocusable : function() {
6164
 
 
6165
 
            this.firstElement = null;
6166
 
            this.lastElement = null;
6167
 
 
6168
 
            var elements = this.getFocusableElements();
6169
 
            this.focusableElements = elements;
6170
 
 
6171
 
            if (elements.length > 0) {
6172
 
                this.firstElement = elements[0];
6173
 
                this.lastElement = elements[elements.length - 1];
6174
 
            }
6175
 
 
6176
 
            if (this.cfg.getProperty("modal")) {
6177
 
                this.setTabLoop(this.firstElement, this.lastElement);
6178
 
            }
6179
 
        },
6180
 
 
6181
 
        /**
6182
 
         * Initializes the custom events for Module which are fired 
6183
 
         * automatically at appropriate times by the Module class.
6184
 
         */
6185
 
        initEvents: function () {
6186
 
            Panel.superclass.initEvents.call(this);
6187
 
 
6188
 
            var SIGNATURE = CustomEvent.LIST;
6189
 
 
6190
 
            /**
6191
 
            * CustomEvent fired after the modality mask is shown
6192
 
            * @event showMaskEvent
6193
 
            */
6194
 
            this.showMaskEvent = this.createEvent(EVENT_TYPES.SHOW_MASK);
6195
 
            this.showMaskEvent.signature = SIGNATURE;
6196
 
 
6197
 
            /**
6198
 
            * CustomEvent fired after the modality mask is hidden
6199
 
            * @event hideMaskEvent
6200
 
            */
6201
 
            this.hideMaskEvent = this.createEvent(EVENT_TYPES.HIDE_MASK);
6202
 
            this.hideMaskEvent.signature = SIGNATURE;
6203
 
 
6204
 
            /**
6205
 
            * CustomEvent when the Panel is dragged
6206
 
            * @event dragEvent
6207
 
            */
6208
 
            this.dragEvent = this.createEvent(EVENT_TYPES.DRAG);
6209
 
            this.dragEvent.signature = SIGNATURE;
6210
 
        },
6211
 
 
6212
 
        /**
6213
 
         * Initializes the class's configurable properties which can be changed 
6214
 
         * using the Panel's Config object (cfg).
6215
 
         * @method initDefaultConfig
6216
 
         */
6217
 
        initDefaultConfig: function () {
6218
 
            Panel.superclass.initDefaultConfig.call(this);
6219
 
 
6220
 
            // Add panel config properties //
6221
 
 
6222
 
            /**
6223
 
            * True if the Panel should display a "close" button
6224
 
            * @config close
6225
 
            * @type Boolean
6226
 
            * @default true
6227
 
            */
6228
 
            this.cfg.addProperty(DEFAULT_CONFIG.CLOSE.key, { 
6229
 
                handler: this.configClose, 
6230
 
                value: DEFAULT_CONFIG.CLOSE.value, 
6231
 
                validator: DEFAULT_CONFIG.CLOSE.validator, 
6232
 
                supercedes: DEFAULT_CONFIG.CLOSE.supercedes 
6233
 
            });
6234
 
 
6235
 
            /**
6236
 
            * Boolean specifying if the Panel should be draggable.  The default 
6237
 
            * value is "true" if the Drag and Drop utility is included, 
6238
 
            * otherwise it is "false." <strong>PLEASE NOTE:</strong> There is a 
6239
 
            * known issue in IE 6 (Strict Mode and Quirks Mode) and IE 7 
6240
 
            * (Quirks Mode) where Panels that either don't have a value set for 
6241
 
            * their "width" configuration property, or their "width" 
6242
 
            * configuration property is set to "auto" will only be draggable by
6243
 
            * placing the mouse on the text of the Panel's header element.
6244
 
            * To fix this bug, draggable Panels missing a value for their 
6245
 
            * "width" configuration property, or whose "width" configuration 
6246
 
            * property is set to "auto" will have it set to the value of 
6247
 
            * their root HTML element's offsetWidth before they are made 
6248
 
            * visible.  The calculated width is then removed when the Panel is   
6249
 
            * hidden. <em>This fix is only applied to draggable Panels in IE 6 
6250
 
            * (Strict Mode and Quirks Mode) and IE 7 (Quirks Mode)</em>. For 
6251
 
            * more information on this issue see:
6252
 
            * SourceForge bugs #1726972 and #1589210.
6253
 
            * @config draggable
6254
 
            * @type Boolean
6255
 
            * @default true
6256
 
            */
6257
 
            this.cfg.addProperty(DEFAULT_CONFIG.DRAGGABLE.key, {
6258
 
                handler: this.configDraggable,
6259
 
                value: (Util.DD) ? true : false,
6260
 
                validator: DEFAULT_CONFIG.DRAGGABLE.validator,
6261
 
                supercedes: DEFAULT_CONFIG.DRAGGABLE.supercedes
6262
 
            });
6263
 
 
6264
 
            /**
6265
 
            * Boolean specifying if the draggable Panel should be drag only, not interacting with drop 
6266
 
            * targets on the page.
6267
 
            * <p>
6268
 
            * When set to true, draggable Panels will not check to see if they are over drop targets,
6269
 
            * or fire the DragDrop events required to support drop target interaction (onDragEnter, 
6270
 
            * onDragOver, onDragOut, onDragDrop etc.).
6271
 
            * If the Panel is not designed to be dropped on any target elements on the page, then this 
6272
 
            * flag can be set to true to improve performance.
6273
 
            * </p>
6274
 
            * <p>
6275
 
            * When set to false, all drop target related events will be fired.
6276
 
            * </p>
6277
 
            * <p>
6278
 
            * The property is set to false by default to maintain backwards compatibility but should be 
6279
 
            * set to true if drop target interaction is not required for the Panel, to improve performance.</p>
6280
 
            * 
6281
 
            * @config dragOnly
6282
 
            * @type Boolean
6283
 
            * @default false
6284
 
            */
6285
 
            this.cfg.addProperty(DEFAULT_CONFIG.DRAG_ONLY.key, { 
6286
 
                value: DEFAULT_CONFIG.DRAG_ONLY.value, 
6287
 
                validator: DEFAULT_CONFIG.DRAG_ONLY.validator, 
6288
 
                supercedes: DEFAULT_CONFIG.DRAG_ONLY.supercedes 
6289
 
            });
6290
 
 
6291
 
            /**
6292
 
            * Sets the type of underlay to display for the Panel. Valid values 
6293
 
            * are "shadow," "matte," and "none".  <strong>PLEASE NOTE:</strong> 
6294
 
            * The creation of the underlay element is deferred until the Panel 
6295
 
            * is initially made visible.  For Gecko-based browsers on Mac
6296
 
            * OS X the underlay elment is always created as it is used as a 
6297
 
            * shim to prevent Aqua scrollbars below a Panel instance from poking 
6298
 
            * through it (See SourceForge bug #836476).
6299
 
            * @config underlay
6300
 
            * @type String
6301
 
            * @default shadow
6302
 
            */
6303
 
            this.cfg.addProperty(DEFAULT_CONFIG.UNDERLAY.key, { 
6304
 
                handler: this.configUnderlay, 
6305
 
                value: DEFAULT_CONFIG.UNDERLAY.value, 
6306
 
                supercedes: DEFAULT_CONFIG.UNDERLAY.supercedes 
6307
 
            });
6308
 
        
6309
 
            /**
6310
 
            * True if the Panel should be displayed in a modal fashion, 
6311
 
            * automatically creating a transparent mask over the document that
6312
 
            * will not be removed until the Panel is dismissed.
6313
 
            * @config modal
6314
 
            * @type Boolean
6315
 
            * @default false
6316
 
            */
6317
 
            this.cfg.addProperty(DEFAULT_CONFIG.MODAL.key, { 
6318
 
                handler: this.configModal, 
6319
 
                value: DEFAULT_CONFIG.MODAL.value,
6320
 
                validator: DEFAULT_CONFIG.MODAL.validator, 
6321
 
                supercedes: DEFAULT_CONFIG.MODAL.supercedes 
6322
 
            });
6323
 
 
6324
 
            /**
6325
 
            * A KeyListener (or array of KeyListeners) that will be enabled 
6326
 
            * when the Panel is shown, and disabled when the Panel is hidden.
6327
 
            * @config keylisteners
6328
 
            * @type YAHOO.util.KeyListener[]
6329
 
            * @default null
6330
 
            */
6331
 
            this.cfg.addProperty(DEFAULT_CONFIG.KEY_LISTENERS.key, { 
6332
 
                handler: this.configKeyListeners, 
6333
 
                suppressEvent: DEFAULT_CONFIG.KEY_LISTENERS.suppressEvent, 
6334
 
                supercedes: DEFAULT_CONFIG.KEY_LISTENERS.supercedes 
6335
 
            });
6336
 
 
6337
 
            /**
6338
 
            * UI Strings used by the Panel
6339
 
            * 
6340
 
            * @config strings
6341
 
            * @type Object
6342
 
            * @default An object literal with the properties shown below:
6343
 
            *     <dl>
6344
 
            *         <dt>close</dt><dd><em>String</em> : The string to use for the close icon. Defaults to "Close".</dd>
6345
 
            *     </dl>
6346
 
            */
6347
 
            this.cfg.addProperty(DEFAULT_CONFIG.STRINGS.key, { 
6348
 
                value:DEFAULT_CONFIG.STRINGS.value,
6349
 
                handler:this.configStrings,
6350
 
                validator:DEFAULT_CONFIG.STRINGS.validator,
6351
 
                supercedes:DEFAULT_CONFIG.STRINGS.supercedes
6352
 
            });
6353
 
        },
6354
 
 
6355
 
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
6356
 
        
6357
 
        /**
6358
 
        * The default event handler fired when the "close" property is changed.
6359
 
        * The method controls the appending or hiding of the close icon at the 
6360
 
        * top right of the Panel.
6361
 
        * @method configClose
6362
 
        * @param {String} type The CustomEvent type (usually the property name)
6363
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6364
 
        * handlers, args[0] will equal the newly applied value for the property.
6365
 
        * @param {Object} obj The scope object. For configuration handlers, 
6366
 
        * this will usually equal the owner.
6367
 
        */
6368
 
        configClose: function (type, args, obj) {
6369
 
 
6370
 
            var val = args[0],
6371
 
                oClose = this.close,
6372
 
                strings = this.cfg.getProperty("strings");
6373
 
 
6374
 
            if (val) {
6375
 
                if (!oClose) {
6376
 
 
6377
 
                    if (!m_oCloseIconTemplate) {
6378
 
                        m_oCloseIconTemplate = document.createElement("a");
6379
 
                        m_oCloseIconTemplate.className = "container-close";
6380
 
                        m_oCloseIconTemplate.href = "#";
6381
 
                    }
6382
 
 
6383
 
                    oClose = m_oCloseIconTemplate.cloneNode(true);
6384
 
                    this.innerElement.appendChild(oClose);
6385
 
 
6386
 
                    oClose.innerHTML = (strings && strings.close) ? strings.close : "&#160;";
6387
 
 
6388
 
                    Event.on(oClose, "click", this._doClose, this, true);
6389
 
 
6390
 
                    this.close = oClose;
6391
 
 
6392
 
                } else {
6393
 
                    oClose.style.display = "block";
6394
 
                }
6395
 
 
6396
 
            } else {
6397
 
                if (oClose) {
6398
 
                    oClose.style.display = "none";
6399
 
                }
6400
 
            }
6401
 
 
6402
 
        },
6403
 
 
6404
 
        /**
6405
 
         * Event handler for the close icon
6406
 
         * 
6407
 
         * @method _doClose
6408
 
         * @protected
6409
 
         * 
6410
 
         * @param {DOMEvent} e
6411
 
         */
6412
 
        _doClose : function (e) {
6413
 
            Event.preventDefault(e);
6414
 
            this.hide();
6415
 
        },
6416
 
 
6417
 
        /**
6418
 
        * The default event handler fired when the "draggable" property 
6419
 
        * is changed.
6420
 
        * @method configDraggable
6421
 
        * @param {String} type The CustomEvent type (usually the property name)
6422
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6423
 
        * handlers, args[0] will equal the newly applied value for the property.
6424
 
        * @param {Object} obj The scope object. For configuration handlers, 
6425
 
        * this will usually equal the owner.
6426
 
        */
6427
 
        configDraggable: function (type, args, obj) {
6428
 
            var val = args[0];
6429
 
 
6430
 
            if (val) {
6431
 
                if (!Util.DD) {
6432
 
                    YAHOO.log("DD dependency not met.", "error");
6433
 
                    this.cfg.setProperty("draggable", false);
6434
 
                    return;
6435
 
                }
6436
 
 
6437
 
                if (this.header) {
6438
 
                    Dom.setStyle(this.header, "cursor", "move");
6439
 
                    this.registerDragDrop();
6440
 
                }
6441
 
 
6442
 
                this.subscribe("beforeShow", setWidthToOffsetWidth);
6443
 
 
6444
 
            } else {
6445
 
 
6446
 
                if (this.dd) {
6447
 
                    this.dd.unreg();
6448
 
                }
6449
 
 
6450
 
                if (this.header) {
6451
 
                    Dom.setStyle(this.header,"cursor","auto");
6452
 
                }
6453
 
 
6454
 
                this.unsubscribe("beforeShow", setWidthToOffsetWidth);
6455
 
            }
6456
 
        },
6457
 
      
6458
 
        /**
6459
 
        * The default event handler fired when the "underlay" property 
6460
 
        * is changed.
6461
 
        * @method configUnderlay
6462
 
        * @param {String} type The CustomEvent type (usually the property name)
6463
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6464
 
        * handlers, args[0] will equal the newly applied value for the property.
6465
 
        * @param {Object} obj The scope object. For configuration handlers, 
6466
 
        * this will usually equal the owner.
6467
 
        */
6468
 
        configUnderlay: function (type, args, obj) {
6469
 
 
6470
 
            var bMacGecko = (this.platform == "mac" && UA.gecko),
6471
 
                sUnderlay = args[0].toLowerCase(),
6472
 
                oUnderlay = this.underlay,
6473
 
                oElement = this.element;
6474
 
 
6475
 
            function createUnderlay() {
6476
 
                var bNew = false;
6477
 
                if (!oUnderlay) { // create if not already in DOM
6478
 
 
6479
 
                    if (!m_oUnderlayTemplate) {
6480
 
                        m_oUnderlayTemplate = document.createElement("div");
6481
 
                        m_oUnderlayTemplate.className = "underlay";
6482
 
                    }
6483
 
 
6484
 
                    oUnderlay = m_oUnderlayTemplate.cloneNode(false);
6485
 
                    this.element.appendChild(oUnderlay);
6486
 
 
6487
 
                    this.underlay = oUnderlay;
6488
 
 
6489
 
                    if (bIEQuirks) {
6490
 
                        this.sizeUnderlay();
6491
 
                        this.cfg.subscribeToConfigEvent("width", this.sizeUnderlay);
6492
 
                        this.cfg.subscribeToConfigEvent("height", this.sizeUnderlay);
6493
 
 
6494
 
                        this.changeContentEvent.subscribe(this.sizeUnderlay);
6495
 
                        YAHOO.widget.Module.textResizeEvent.subscribe(this.sizeUnderlay, this, true);
6496
 
                    }
6497
 
 
6498
 
                    if (UA.webkit && UA.webkit < 420) {
6499
 
                        this.changeContentEvent.subscribe(this.forceUnderlayRedraw);
6500
 
                    }
6501
 
 
6502
 
                    bNew = true;
6503
 
                }
6504
 
            }
6505
 
 
6506
 
            function onBeforeShow() {
6507
 
                var bNew = createUnderlay.call(this);
6508
 
                if (!bNew && bIEQuirks) {
6509
 
                    this.sizeUnderlay();
6510
 
                }
6511
 
                this._underlayDeferred = false;
6512
 
                this.beforeShowEvent.unsubscribe(onBeforeShow);
6513
 
            }
6514
 
 
6515
 
            function destroyUnderlay() {
6516
 
                if (this._underlayDeferred) {
6517
 
                    this.beforeShowEvent.unsubscribe(onBeforeShow);
6518
 
                    this._underlayDeferred = false;
6519
 
                }
6520
 
 
6521
 
                if (oUnderlay) {
6522
 
                    this.cfg.unsubscribeFromConfigEvent("width", this.sizeUnderlay);
6523
 
                    this.cfg.unsubscribeFromConfigEvent("height",this.sizeUnderlay);
6524
 
                    this.changeContentEvent.unsubscribe(this.sizeUnderlay);
6525
 
                    this.changeContentEvent.unsubscribe(this.forceUnderlayRedraw);
6526
 
                    YAHOO.widget.Module.textResizeEvent.unsubscribe(this.sizeUnderlay, this, true);
6527
 
 
6528
 
                    this.element.removeChild(oUnderlay);
6529
 
 
6530
 
                    this.underlay = null;
6531
 
                }
6532
 
            }
6533
 
 
6534
 
            switch (sUnderlay) {
6535
 
                case "shadow":
6536
 
                    Dom.removeClass(oElement, "matte");
6537
 
                    Dom.addClass(oElement, "shadow");
6538
 
                    break;
6539
 
                case "matte":
6540
 
                    if (!bMacGecko) {
6541
 
                        destroyUnderlay.call(this);
6542
 
                    }
6543
 
                    Dom.removeClass(oElement, "shadow");
6544
 
                    Dom.addClass(oElement, "matte");
6545
 
                    break;
6546
 
                default:
6547
 
                    if (!bMacGecko) {
6548
 
                        destroyUnderlay.call(this);
6549
 
                    }
6550
 
                    Dom.removeClass(oElement, "shadow");
6551
 
                    Dom.removeClass(oElement, "matte");
6552
 
                    break;
6553
 
            }
6554
 
 
6555
 
            if ((sUnderlay == "shadow") || (bMacGecko && !oUnderlay)) {
6556
 
                if (this.cfg.getProperty("visible")) {
6557
 
                    var bNew = createUnderlay.call(this);
6558
 
                    if (!bNew && bIEQuirks) {
6559
 
                        this.sizeUnderlay();
6560
 
                    }
6561
 
                } else {
6562
 
                    if (!this._underlayDeferred) {
6563
 
                        this.beforeShowEvent.subscribe(onBeforeShow);
6564
 
                        this._underlayDeferred = true;
6565
 
                    }
6566
 
                }
6567
 
            }
6568
 
        },
6569
 
        
6570
 
        /**
6571
 
        * The default event handler fired when the "modal" property is 
6572
 
        * changed. This handler subscribes or unsubscribes to the show and hide
6573
 
        * events to handle the display or hide of the modality mask.
6574
 
        * @method configModal
6575
 
        * @param {String} type The CustomEvent type (usually the property name)
6576
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6577
 
        * handlers, args[0] will equal the newly applied value for the property.
6578
 
        * @param {Object} obj The scope object. For configuration handlers, 
6579
 
        * this will usually equal the owner.
6580
 
        */
6581
 
        configModal: function (type, args, obj) {
6582
 
 
6583
 
            var modal = args[0];
6584
 
            if (modal) {
6585
 
                if (!this._hasModalityEventListeners) {
6586
 
 
6587
 
                    this.subscribe("beforeShow", this.buildMask);
6588
 
                    this.subscribe("beforeShow", this.bringToTop);
6589
 
                    this.subscribe("beforeShow", this.showMask);
6590
 
                    this.subscribe("hide", this.hideMask);
6591
 
 
6592
 
                    Overlay.windowResizeEvent.subscribe(this.sizeMask, 
6593
 
                        this, true);
6594
 
 
6595
 
                    this._hasModalityEventListeners = true;
6596
 
                }
6597
 
            } else {
6598
 
                if (this._hasModalityEventListeners) {
6599
 
 
6600
 
                    if (this.cfg.getProperty("visible")) {
6601
 
                        this.hideMask();
6602
 
                        this.removeMask();
6603
 
                    }
6604
 
 
6605
 
                    this.unsubscribe("beforeShow", this.buildMask);
6606
 
                    this.unsubscribe("beforeShow", this.bringToTop);
6607
 
                    this.unsubscribe("beforeShow", this.showMask);
6608
 
                    this.unsubscribe("hide", this.hideMask);
6609
 
 
6610
 
                    Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
6611
 
 
6612
 
                    this._hasModalityEventListeners = false;
6613
 
                }
6614
 
            }
6615
 
        },
6616
 
 
6617
 
        /**
6618
 
        * Removes the modality mask.
6619
 
        * @method removeMask
6620
 
        */
6621
 
        removeMask: function () {
6622
 
 
6623
 
            var oMask = this.mask,
6624
 
                oParentNode;
6625
 
 
6626
 
            if (oMask) {
6627
 
                /*
6628
 
                    Hide the mask before destroying it to ensure that DOM
6629
 
                    event handlers on focusable elements get removed.
6630
 
                */
6631
 
                this.hideMask();
6632
 
 
6633
 
                oParentNode = oMask.parentNode;
6634
 
                if (oParentNode) {
6635
 
                    oParentNode.removeChild(oMask);
6636
 
                }
6637
 
 
6638
 
                this.mask = null;
6639
 
            }
6640
 
        },
6641
 
        
6642
 
        /**
6643
 
        * The default event handler fired when the "keylisteners" property 
6644
 
        * is changed.
6645
 
        * @method configKeyListeners
6646
 
        * @param {String} type The CustomEvent type (usually the property name)
6647
 
        * @param {Object[]} args The CustomEvent arguments. For configuration
6648
 
        * handlers, args[0] will equal the newly applied value for the property.
6649
 
        * @param {Object} obj The scope object. For configuration handlers, 
6650
 
        * this will usually equal the owner.
6651
 
        */
6652
 
        configKeyListeners: function (type, args, obj) {
6653
 
 
6654
 
            var listeners = args[0],
6655
 
                listener,
6656
 
                nListeners,
6657
 
                i;
6658
 
        
6659
 
            if (listeners) {
6660
 
 
6661
 
                if (listeners instanceof Array) {
6662
 
 
6663
 
                    nListeners = listeners.length;
6664
 
 
6665
 
                    for (i = 0; i < nListeners; i++) {
6666
 
 
6667
 
                        listener = listeners[i];
6668
 
        
6669
 
                        if (!Config.alreadySubscribed(this.showEvent, 
6670
 
                            listener.enable, listener)) {
6671
 
 
6672
 
                            this.showEvent.subscribe(listener.enable, 
6673
 
                                listener, true);
6674
 
 
6675
 
                        }
6676
 
 
6677
 
                        if (!Config.alreadySubscribed(this.hideEvent, 
6678
 
                            listener.disable, listener)) {
6679
 
 
6680
 
                            this.hideEvent.subscribe(listener.disable, 
6681
 
                                listener, true);
6682
 
 
6683
 
                            this.destroyEvent.subscribe(listener.disable, 
6684
 
                                listener, true);
6685
 
                        }
6686
 
                    }
6687
 
 
6688
 
                } else {
6689
 
 
6690
 
                    if (!Config.alreadySubscribed(this.showEvent, 
6691
 
                        listeners.enable, listeners)) {
6692
 
 
6693
 
                        this.showEvent.subscribe(listeners.enable, 
6694
 
                            listeners, true);
6695
 
                    }
6696
 
 
6697
 
                    if (!Config.alreadySubscribed(this.hideEvent, 
6698
 
                        listeners.disable, listeners)) {
6699
 
 
6700
 
                        this.hideEvent.subscribe(listeners.disable, 
6701
 
                            listeners, true);
6702
 
 
6703
 
                        this.destroyEvent.subscribe(listeners.disable, 
6704
 
                            listeners, true);
6705
 
 
6706
 
                    }
6707
 
 
6708
 
                }
6709
 
 
6710
 
            }
6711
 
 
6712
 
        },
6713
 
 
6714
 
        /**
6715
 
        * The default handler for the "strings" property
6716
 
        * @method configStrings
6717
 
        */
6718
 
        configStrings : function(type, args, obj) {
6719
 
            var val = Lang.merge(DEFAULT_CONFIG.STRINGS.value, args[0]);
6720
 
            this.cfg.setProperty(DEFAULT_CONFIG.STRINGS.key, val, true);
6721
 
        },
6722
 
 
6723
 
        /**
6724
 
        * The default event handler fired when the "height" property is changed.
6725
 
        * @method configHeight
6726
 
        * @param {String} type The CustomEvent type (usually the property name)
6727
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6728
 
        * handlers, args[0] will equal the newly applied value for the property.
6729
 
        * @param {Object} obj The scope object. For configuration handlers, 
6730
 
        * this will usually equal the owner.
6731
 
        */
6732
 
        configHeight: function (type, args, obj) {
6733
 
            var height = args[0],
6734
 
                el = this.innerElement;
6735
 
 
6736
 
            Dom.setStyle(el, "height", height);
6737
 
            this.cfg.refireEvent("iframe");
6738
 
        },
6739
 
 
6740
 
        /**
6741
 
         * The default custom event handler executed when the Panel's height is changed, 
6742
 
         * if the autofillheight property has been set.
6743
 
         *
6744
 
         * @method _autoFillOnHeightChange
6745
 
         * @protected
6746
 
         * @param {String} type The event type
6747
 
         * @param {Array} args The array of arguments passed to event subscribers
6748
 
         * @param {HTMLElement} el The header, body or footer element which is to be resized to fill
6749
 
         * out the containers height
6750
 
         */
6751
 
        _autoFillOnHeightChange : function(type, args, el) {
6752
 
            Panel.superclass._autoFillOnHeightChange.apply(this, arguments);
6753
 
            if (bIEQuirks) {
6754
 
                var panel = this;
6755
 
                setTimeout(function() {
6756
 
                    panel.sizeUnderlay();
6757
 
                },0);
6758
 
            }
6759
 
        },
6760
 
 
6761
 
        /**
6762
 
        * The default event handler fired when the "width" property is changed.
6763
 
        * @method configWidth
6764
 
        * @param {String} type The CustomEvent type (usually the property name)
6765
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6766
 
        * handlers, args[0] will equal the newly applied value for the property.
6767
 
        * @param {Object} obj The scope object. For configuration handlers, 
6768
 
        * this will usually equal the owner.
6769
 
        */
6770
 
        configWidth: function (type, args, obj) {
6771
 
    
6772
 
            var width = args[0],
6773
 
                el = this.innerElement;
6774
 
    
6775
 
            Dom.setStyle(el, "width", width);
6776
 
            this.cfg.refireEvent("iframe");
6777
 
    
6778
 
        },
6779
 
        
6780
 
        /**
6781
 
        * The default event handler fired when the "zIndex" property is changed.
6782
 
        * @method configzIndex
6783
 
        * @param {String} type The CustomEvent type (usually the property name)
6784
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
6785
 
        * handlers, args[0] will equal the newly applied value for the property.
6786
 
        * @param {Object} obj The scope object. For configuration handlers, 
6787
 
        * this will usually equal the owner.
6788
 
        */
6789
 
        configzIndex: function (type, args, obj) {
6790
 
            Panel.superclass.configzIndex.call(this, type, args, obj);
6791
 
 
6792
 
            if (this.mask || this.cfg.getProperty("modal") === true) {
6793
 
                var panelZ = Dom.getStyle(this.element, "zIndex");
6794
 
                if (!panelZ || isNaN(panelZ)) {
6795
 
                    panelZ = 0;
6796
 
                }
6797
 
 
6798
 
                if (panelZ === 0) {
6799
 
                    // Recursive call to configzindex (which should be stopped
6800
 
                    // from going further because panelZ should no longer === 0)
6801
 
                    this.cfg.setProperty("zIndex", 1);
6802
 
                } else {
6803
 
                    this.stackMask();
6804
 
                }
6805
 
            }
6806
 
        },
6807
 
 
6808
 
        // END BUILT-IN PROPERTY EVENT HANDLERS //
6809
 
        /**
6810
 
        * Builds the wrapping container around the Panel that is used for 
6811
 
        * positioning the shadow and matte underlays. The container element is 
6812
 
        * assigned to a  local instance variable called container, and the 
6813
 
        * element is reinserted inside of it.
6814
 
        * @method buildWrapper
6815
 
        */
6816
 
        buildWrapper: function () {
6817
 
 
6818
 
            var elementParent = this.element.parentNode,
6819
 
                originalElement = this.element,
6820
 
                wrapper = document.createElement("div");
6821
 
 
6822
 
            wrapper.className = Panel.CSS_PANEL_CONTAINER;
6823
 
            wrapper.id = originalElement.id + "_c";
6824
 
 
6825
 
            if (elementParent) {
6826
 
                elementParent.insertBefore(wrapper, originalElement);
6827
 
            }
6828
 
 
6829
 
            wrapper.appendChild(originalElement);
6830
 
 
6831
 
            this.element = wrapper;
6832
 
            this.innerElement = originalElement;
6833
 
 
6834
 
            Dom.setStyle(this.innerElement, "visibility", "inherit");
6835
 
        },
6836
 
 
6837
 
        /**
6838
 
        * Adjusts the size of the shadow based on the size of the element.
6839
 
        * @method sizeUnderlay
6840
 
        */
6841
 
        sizeUnderlay: function () {
6842
 
            var oUnderlay = this.underlay,
6843
 
                oElement;
6844
 
 
6845
 
            if (oUnderlay) {
6846
 
                oElement = this.element;
6847
 
                oUnderlay.style.width = oElement.offsetWidth + "px";
6848
 
                oUnderlay.style.height = oElement.offsetHeight + "px";
6849
 
            }
6850
 
        },
6851
 
 
6852
 
        /**
6853
 
        * Registers the Panel's header for drag & drop capability.
6854
 
        * @method registerDragDrop
6855
 
        */
6856
 
        registerDragDrop: function () {
6857
 
 
6858
 
            var me = this;
6859
 
 
6860
 
            if (this.header) {
6861
 
 
6862
 
                if (!Util.DD) {
6863
 
                    YAHOO.log("DD dependency not met.", "error");
6864
 
                    return;
6865
 
                }
6866
 
 
6867
 
                var bDragOnly = (this.cfg.getProperty("dragonly") === true);
6868
 
                this.dd = new Util.DD(this.element.id, this.id, {dragOnly: bDragOnly});
6869
 
 
6870
 
                if (!this.header.id) {
6871
 
                    this.header.id = this.id + "_h";
6872
 
                }
6873
 
 
6874
 
                this.dd.startDrag = function () {
6875
 
 
6876
 
                    var offsetHeight,
6877
 
                        offsetWidth,
6878
 
                        viewPortWidth,
6879
 
                        viewPortHeight,
6880
 
                        scrollX,
6881
 
                        scrollY;
6882
 
 
6883
 
                    if (YAHOO.env.ua.ie == 6) {
6884
 
                        Dom.addClass(me.element,"drag");
6885
 
                    }
6886
 
 
6887
 
                    if (me.cfg.getProperty("constraintoviewport")) {
6888
 
 
6889
 
                        var nViewportOffset = Overlay.VIEWPORT_OFFSET;
6890
 
 
6891
 
                        offsetHeight = me.element.offsetHeight;
6892
 
                        offsetWidth = me.element.offsetWidth;
6893
 
 
6894
 
                        viewPortWidth = Dom.getViewportWidth();
6895
 
                        viewPortHeight = Dom.getViewportHeight();
6896
 
 
6897
 
                        scrollX = Dom.getDocumentScrollLeft();
6898
 
                        scrollY = Dom.getDocumentScrollTop();
6899
 
 
6900
 
                        if (offsetHeight + nViewportOffset < viewPortHeight) {
6901
 
                            this.minY = scrollY + nViewportOffset;
6902
 
                            this.maxY = scrollY + viewPortHeight - offsetHeight - nViewportOffset;
6903
 
                        } else {
6904
 
                            this.minY = scrollY + nViewportOffset;
6905
 
                            this.maxY = scrollY + nViewportOffset;
6906
 
                        }
6907
 
 
6908
 
                        if (offsetWidth + nViewportOffset < viewPortWidth) {
6909
 
                            this.minX = scrollX + nViewportOffset;
6910
 
                            this.maxX = scrollX + viewPortWidth - offsetWidth - nViewportOffset;
6911
 
                        } else {
6912
 
                            this.minX = scrollX + nViewportOffset;
6913
 
                            this.maxX = scrollX + nViewportOffset;
6914
 
                        }
6915
 
 
6916
 
                        this.constrainX = true;
6917
 
                        this.constrainY = true;
6918
 
                    } else {
6919
 
                        this.constrainX = false;
6920
 
                        this.constrainY = false;
6921
 
                    }
6922
 
 
6923
 
                    me.dragEvent.fire("startDrag", arguments);
6924
 
                };
6925
 
 
6926
 
                this.dd.onDrag = function () {
6927
 
                    me.syncPosition();
6928
 
                    me.cfg.refireEvent("iframe");
6929
 
                    if (this.platform == "mac" && YAHOO.env.ua.gecko) {
6930
 
                        this.showMacGeckoScrollbars();
6931
 
                    }
6932
 
 
6933
 
                    me.dragEvent.fire("onDrag", arguments);
6934
 
                };
6935
 
 
6936
 
                this.dd.endDrag = function () {
6937
 
 
6938
 
                    if (YAHOO.env.ua.ie == 6) {
6939
 
                        Dom.removeClass(me.element,"drag");
6940
 
                    }
6941
 
 
6942
 
                    me.dragEvent.fire("endDrag", arguments);
6943
 
                    me.moveEvent.fire(me.cfg.getProperty("xy"));
6944
 
 
6945
 
                };
6946
 
 
6947
 
                this.dd.setHandleElId(this.header.id);
6948
 
                this.dd.addInvalidHandleType("INPUT");
6949
 
                this.dd.addInvalidHandleType("SELECT");
6950
 
                this.dd.addInvalidHandleType("TEXTAREA");
6951
 
            }
6952
 
        },
6953
 
        
6954
 
        /**
6955
 
        * Builds the mask that is laid over the document when the Panel is 
6956
 
        * configured to be modal.
6957
 
        * @method buildMask
6958
 
        */
6959
 
        buildMask: function () {
6960
 
            var oMask = this.mask;
6961
 
            if (!oMask) {
6962
 
                if (!m_oMaskTemplate) {
6963
 
                    m_oMaskTemplate = document.createElement("div");
6964
 
                    m_oMaskTemplate.className = "mask";
6965
 
                    m_oMaskTemplate.innerHTML = "&#160;";
6966
 
                }
6967
 
                oMask = m_oMaskTemplate.cloneNode(true);
6968
 
                oMask.id = this.id + "_mask";
6969
 
 
6970
 
                document.body.insertBefore(oMask, document.body.firstChild);
6971
 
 
6972
 
                this.mask = oMask;
6973
 
 
6974
 
                if (YAHOO.env.ua.gecko && this.platform == "mac") {
6975
 
                    Dom.addClass(this.mask, "block-scrollbars");
6976
 
                }
6977
 
 
6978
 
                // Stack mask based on the element zindex
6979
 
                this.stackMask();
6980
 
            }
6981
 
        },
6982
 
 
6983
 
        /**
6984
 
        * Hides the modality mask.
6985
 
        * @method hideMask
6986
 
        */
6987
 
        hideMask: function () {
6988
 
            if (this.cfg.getProperty("modal") && this.mask) {
6989
 
                this.mask.style.display = "none";
6990
 
                Dom.removeClass(document.body, "masked");
6991
 
                this.hideMaskEvent.fire();
6992
 
            }
6993
 
        },
6994
 
 
6995
 
        /**
6996
 
        * Shows the modality mask.
6997
 
        * @method showMask
6998
 
        */
6999
 
        showMask: function () {
7000
 
            if (this.cfg.getProperty("modal") && this.mask) {
7001
 
                Dom.addClass(document.body, "masked");
7002
 
                this.sizeMask();
7003
 
                this.mask.style.display = "block";
7004
 
                this.showMaskEvent.fire();
7005
 
            }
7006
 
        },
7007
 
 
7008
 
        /**
7009
 
        * Sets the size of the modality mask to cover the entire scrollable 
7010
 
        * area of the document
7011
 
        * @method sizeMask
7012
 
        */
7013
 
        sizeMask: function () {
7014
 
            if (this.mask) {
7015
 
 
7016
 
                // Shrink mask first, so it doesn't affect the document size.
7017
 
                var mask = this.mask,
7018
 
                    viewWidth = Dom.getViewportWidth(),
7019
 
                    viewHeight = Dom.getViewportHeight();
7020
 
 
7021
 
                if (mask.offsetHeight > viewHeight) {
7022
 
                    mask.style.height = viewHeight + "px";
7023
 
                }
7024
 
 
7025
 
                if (mask.offsetWidth > viewWidth) {
7026
 
                    mask.style.width = viewWidth + "px";
7027
 
                }
7028
 
 
7029
 
                // Then size it to the document
7030
 
                mask.style.height = Dom.getDocumentHeight() + "px";
7031
 
                mask.style.width = Dom.getDocumentWidth() + "px";
7032
 
            }
7033
 
        },
7034
 
 
7035
 
        /**
7036
 
         * Sets the zindex of the mask, if it exists, based on the zindex of 
7037
 
         * the Panel element. The zindex of the mask is set to be one less 
7038
 
         * than the Panel element's zindex.
7039
 
         * 
7040
 
         * <p>NOTE: This method will not bump up the zindex of the Panel
7041
 
         * to ensure that the mask has a non-negative zindex. If you require the
7042
 
         * mask zindex to be 0 or higher, the zindex of the Panel 
7043
 
         * should be set to a value higher than 0, before this method is called.
7044
 
         * </p>
7045
 
         * @method stackMask
7046
 
         */
7047
 
        stackMask: function() {
7048
 
            if (this.mask) {
7049
 
                var panelZ = Dom.getStyle(this.element, "zIndex");
7050
 
                if (!YAHOO.lang.isUndefined(panelZ) && !isNaN(panelZ)) {
7051
 
                    Dom.setStyle(this.mask, "zIndex", panelZ - 1);
7052
 
                }
7053
 
            }
7054
 
        },
7055
 
 
7056
 
        /**
7057
 
        * Renders the Panel by inserting the elements that are not already in 
7058
 
        * the main Panel into their correct places. Optionally appends the 
7059
 
        * Panel to the specified node prior to the render's execution. NOTE: 
7060
 
        * For Panels without existing markup, the appendToNode argument is 
7061
 
        * REQUIRED. If this argument is ommitted and the current element is 
7062
 
        * not present in the document, the function will return false, 
7063
 
        * indicating that the render was a failure.
7064
 
        * @method render
7065
 
        * @param {String} appendToNode The element id to which the Module 
7066
 
        * should be appended to prior to rendering <em>OR</em>
7067
 
        * @param {HTMLElement} appendToNode The element to which the Module 
7068
 
        * should be appended to prior to rendering
7069
 
        * @return {boolean} Success or failure of the render
7070
 
        */
7071
 
        render: function (appendToNode) {
7072
 
 
7073
 
            return Panel.superclass.render.call(this, 
7074
 
                appendToNode, this.innerElement);
7075
 
 
7076
 
        },
7077
 
        
7078
 
        /**
7079
 
        * Removes the Panel element from the DOM and sets all child elements
7080
 
        * to null.
7081
 
        * @method destroy
7082
 
        */
7083
 
        destroy: function () {
7084
 
            Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
7085
 
            this.removeMask();
7086
 
            if (this.close) {
7087
 
                Event.purgeElement(this.close);
7088
 
            }
7089
 
            Panel.superclass.destroy.call(this);  
7090
 
        },
7091
 
 
7092
 
        /**
7093
 
         * Forces the underlay element to be repainted through the application/removal 
7094
 
         * of a yui-force-redraw class to the underlay element.
7095
 
         *
7096
 
         * @method forceUnderlayRedraw
7097
 
         */
7098
 
        forceUnderlayRedraw : function () {
7099
 
            var u = this.underlay;
7100
 
            Dom.addClass(u, "yui-force-redraw");
7101
 
            setTimeout(function(){Dom.removeClass(u, "yui-force-redraw");}, 0);
7102
 
        },
7103
 
 
7104
 
        /**
7105
 
        * Returns a String representation of the object.
7106
 
        * @method toString
7107
 
        * @return {String} The string representation of the Panel.
7108
 
        */
7109
 
        toString: function () {
7110
 
            return "Panel " + this.id;
7111
 
        }
7112
 
    
7113
 
    });
7114
 
 
7115
 
}());
7116
 
 
7117
 
(function () {
7118
 
 
7119
 
    /**
7120
 
    * <p>
7121
 
    * Dialog is an implementation of Panel that can be used to submit form 
7122
 
    * data.
7123
 
    * </p>
7124
 
    * <p>
7125
 
    * Built-in functionality for buttons with event handlers is included. 
7126
 
    * If the optional YUI Button dependancy is included on the page, the buttons
7127
 
    * created will be instances of YAHOO.widget.Button, otherwise regular HTML buttons
7128
 
    * will be created.
7129
 
    * </p>
7130
 
    * <p>
7131
 
    * Forms can be processed in 3 ways -- via an asynchronous Connection utility call, 
7132
 
    * a simple form POST or GET, or manually. The YUI Connection utility should be
7133
 
    * included if you're using the default "async" postmethod, but is not required if
7134
 
    * you're using any of the other postmethod values.
7135
 
    * </p>
7136
 
    * @namespace YAHOO.widget
7137
 
    * @class Dialog
7138
 
    * @extends YAHOO.widget.Panel
7139
 
    * @constructor
7140
 
    * @param {String} el The element ID representing the Dialog <em>OR</em>
7141
 
    * @param {HTMLElement} el The element representing the Dialog
7142
 
    * @param {Object} userConfig The configuration object literal containing 
7143
 
    * the configuration that should be set for this Dialog. See configuration 
7144
 
    * documentation for more details.
7145
 
    */
7146
 
    YAHOO.widget.Dialog = function (el, userConfig) {
7147
 
        YAHOO.widget.Dialog.superclass.constructor.call(this, el, userConfig);
7148
 
    };
7149
 
 
7150
 
    var Event = YAHOO.util.Event,
7151
 
        CustomEvent = YAHOO.util.CustomEvent,
7152
 
        Dom = YAHOO.util.Dom,
7153
 
        Dialog = YAHOO.widget.Dialog,
7154
 
        Lang = YAHOO.lang,
7155
 
 
7156
 
        /**
7157
 
         * Constant representing the name of the Dialog's events
7158
 
         * @property EVENT_TYPES
7159
 
         * @private
7160
 
         * @final
7161
 
         * @type Object
7162
 
         */
7163
 
        EVENT_TYPES = {
7164
 
            "BEFORE_SUBMIT": "beforeSubmit",
7165
 
            "SUBMIT": "submit",
7166
 
            "MANUAL_SUBMIT": "manualSubmit",
7167
 
            "ASYNC_SUBMIT": "asyncSubmit",
7168
 
            "FORM_SUBMIT": "formSubmit",
7169
 
            "CANCEL": "cancel"
7170
 
        },
7171
 
 
7172
 
        /**
7173
 
        * Constant representing the Dialog's configuration properties
7174
 
        * @property DEFAULT_CONFIG
7175
 
        * @private
7176
 
        * @final
7177
 
        * @type Object
7178
 
        */
7179
 
        DEFAULT_CONFIG = {
7180
 
 
7181
 
            "POST_METHOD": { 
7182
 
                key: "postmethod", 
7183
 
                value: "async"
7184
 
            },
7185
 
 
7186
 
            "POST_DATA" : {
7187
 
                key: "postdata",
7188
 
                value: null
7189
 
            },
7190
 
 
7191
 
            "BUTTONS": {
7192
 
                key: "buttons",
7193
 
                value: "none",
7194
 
                supercedes: ["visible"]
7195
 
            },
7196
 
 
7197
 
            "HIDEAFTERSUBMIT" : {
7198
 
                key: "hideaftersubmit",
7199
 
                value: true
7200
 
            }
7201
 
 
7202
 
        };
7203
 
 
7204
 
    /**
7205
 
    * Constant representing the default CSS class used for a Dialog
7206
 
    * @property YAHOO.widget.Dialog.CSS_DIALOG
7207
 
    * @static
7208
 
    * @final
7209
 
    * @type String
7210
 
    */
7211
 
    Dialog.CSS_DIALOG = "yui-dialog";
7212
 
 
7213
 
    function removeButtonEventHandlers() {
7214
 
 
7215
 
        var aButtons = this._aButtons,
7216
 
            nButtons,
7217
 
            oButton,
7218
 
            i;
7219
 
 
7220
 
        if (Lang.isArray(aButtons)) {
7221
 
            nButtons = aButtons.length;
7222
 
 
7223
 
            if (nButtons > 0) {
7224
 
                i = nButtons - 1;
7225
 
                do {
7226
 
                    oButton = aButtons[i];
7227
 
 
7228
 
                    if (YAHOO.widget.Button && oButton instanceof YAHOO.widget.Button) {
7229
 
                        oButton.destroy();
7230
 
                    }
7231
 
                    else if (oButton.tagName.toUpperCase() == "BUTTON") {
7232
 
                        Event.purgeElement(oButton);
7233
 
                        Event.purgeElement(oButton, false);
7234
 
                    }
7235
 
                }
7236
 
                while (i--);
7237
 
            }
7238
 
        }
7239
 
    }
7240
 
 
7241
 
    YAHOO.extend(Dialog, YAHOO.widget.Panel, { 
7242
 
 
7243
 
        /**
7244
 
        * @property form
7245
 
        * @description Object reference to the Dialog's 
7246
 
        * <code>&#60;form&#62;</code> element.
7247
 
        * @default null 
7248
 
        * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
7249
 
        * level-one-html.html#ID-40002357">HTMLFormElement</a>
7250
 
        */
7251
 
        form: null,
7252
 
    
7253
 
        /**
7254
 
        * Initializes the class's configurable properties which can be changed 
7255
 
        * using the Dialog's Config object (cfg).
7256
 
        * @method initDefaultConfig
7257
 
        */
7258
 
        initDefaultConfig: function () {
7259
 
            Dialog.superclass.initDefaultConfig.call(this);
7260
 
 
7261
 
            /**
7262
 
            * The internally maintained callback object for use with the 
7263
 
            * Connection utility. The format of the callback object is 
7264
 
            * similar to Connection Manager's callback object and is 
7265
 
            * simply passed through to Connection Manager when the async 
7266
 
            * request is made.
7267
 
            * @property callback
7268
 
            * @type Object
7269
 
            */
7270
 
            this.callback = {
7271
 
 
7272
 
                /**
7273
 
                * The function to execute upon success of the 
7274
 
                * Connection submission (when the form does not
7275
 
                * contain a file input element).
7276
 
                * 
7277
 
                * @property callback.success
7278
 
                * @type Function
7279
 
                */
7280
 
                success: null,
7281
 
 
7282
 
                /**
7283
 
                * The function to execute upon failure of the 
7284
 
                * Connection submission
7285
 
                * @property callback.failure
7286
 
                * @type Function
7287
 
                */
7288
 
                failure: null,
7289
 
 
7290
 
                /**
7291
 
                *<p>
7292
 
                * The function to execute upon success of the 
7293
 
                * Connection submission, when the form contains
7294
 
                * a file input element.
7295
 
                * </p>
7296
 
                * <p>
7297
 
                * <em>NOTE:</em> Connection manager will not
7298
 
                * invoke the success or failure handlers for the file
7299
 
                * upload use case. This will be the only callback
7300
 
                * handler invoked.
7301
 
                * </p>
7302
 
                * <p>
7303
 
                * For more information, see the <a href="http://developer.yahoo.com/yui/connection/#file">
7304
 
                * Connection Manager documenation on file uploads</a>.
7305
 
                * </p>
7306
 
                * @property callback.upload
7307
 
                * @type Function
7308
 
                */
7309
 
 
7310
 
                /**
7311
 
                * The arbitraty argument or arguments to pass to the Connection 
7312
 
                * callback functions
7313
 
                * @property callback.argument
7314
 
                * @type Object
7315
 
                */
7316
 
                argument: null
7317
 
 
7318
 
            };
7319
 
 
7320
 
            // Add form dialog config properties //
7321
 
            /**
7322
 
            * The method to use for posting the Dialog's form. Possible values 
7323
 
            * are "async", "form", and "manual".
7324
 
            * @config postmethod
7325
 
            * @type String
7326
 
            * @default async
7327
 
            */
7328
 
            this.cfg.addProperty(DEFAULT_CONFIG.POST_METHOD.key, {
7329
 
                handler: this.configPostMethod, 
7330
 
                value: DEFAULT_CONFIG.POST_METHOD.value, 
7331
 
                validator: function (val) {
7332
 
                    if (val != "form" && val != "async" && val != "none" && 
7333
 
                        val != "manual") {
7334
 
                        return false;
7335
 
                    } else {
7336
 
                        return true;
7337
 
                    }
7338
 
                }
7339
 
            });
7340
 
 
7341
 
            /**
7342
 
            * Any additional post data which needs to be sent when using the 
7343
 
            * <a href="#config_postmethod">async</a> postmethod for dialog POST submissions.
7344
 
            * The format for the post data string is defined by Connection Manager's 
7345
 
            * <a href="YAHOO.util.Connect.html#method_asyncRequest">asyncRequest</a> 
7346
 
            * method.
7347
 
            * @config postdata
7348
 
            * @type String
7349
 
            * @default null
7350
 
            */
7351
 
            this.cfg.addProperty(DEFAULT_CONFIG.POST_DATA.key, {
7352
 
                value: DEFAULT_CONFIG.POST_DATA.value
7353
 
            });
7354
 
 
7355
 
            /**
7356
 
            * This property is used to configure whether or not the 
7357
 
            * dialog should be automatically hidden after submit.
7358
 
            * 
7359
 
            * @config hideaftersubmit
7360
 
            * @type Boolean
7361
 
            * @default true
7362
 
            */
7363
 
            this.cfg.addProperty(DEFAULT_CONFIG.HIDEAFTERSUBMIT.key, {
7364
 
                value: DEFAULT_CONFIG.HIDEAFTERSUBMIT.value
7365
 
            });
7366
 
 
7367
 
            /**
7368
 
            * Array of object literals, each containing a set of properties 
7369
 
            * defining a button to be appended into the Dialog's footer.
7370
 
            *
7371
 
            * <p>Each button object in the buttons array can have three properties:</p>
7372
 
            * <dl>
7373
 
            *    <dt>text:</dt>
7374
 
            *    <dd>
7375
 
            *       The text that will display on the face of the button. The text can 
7376
 
            *       include HTML, as long as it is compliant with HTML Button specifications.
7377
 
            *    </dd>
7378
 
            *    <dt>handler:</dt>
7379
 
            *    <dd>Can be either:
7380
 
            *    <ol>
7381
 
            *       <li>A reference to a function that should fire when the 
7382
 
            *       button is clicked.  (In this case scope of this function is 
7383
 
            *       always its Dialog instance.)</li>
7384
 
            *
7385
 
            *       <li>An object literal representing the code to be 
7386
 
            *       executed when the button is clicked.
7387
 
            *       
7388
 
            *       <p>Format:</p>
7389
 
            *
7390
 
            *       <p>
7391
 
            *       <code>{
7392
 
            *       <br>
7393
 
            *       <strong>fn:</strong> Function, &#47;&#47;
7394
 
            *       The handler to call when  the event fires.
7395
 
            *       <br>
7396
 
            *       <strong>obj:</strong> Object, &#47;&#47; 
7397
 
            *       An  object to pass back to the handler.
7398
 
            *       <br>
7399
 
            *       <strong>scope:</strong> Object &#47;&#47; 
7400
 
            *       The object to use for the scope of the handler.
7401
 
            *       <br>
7402
 
            *       }</code>
7403
 
            *       </p>
7404
 
            *       </li>
7405
 
            *     </ol>
7406
 
            *     </dd>
7407
 
            *     <dt>isDefault:</dt>
7408
 
            *     <dd>
7409
 
            *        An optional boolean value that specifies that a button 
7410
 
            *        should be highlighted and focused by default.
7411
 
            *     </dd>
7412
 
            * </dl>
7413
 
            *
7414
 
            * <em>NOTE:</em>If the YUI Button Widget is included on the page, 
7415
 
            * the buttons created will be instances of YAHOO.widget.Button. 
7416
 
            * Otherwise, HTML Buttons (<code>&#60;BUTTON&#62;</code>) will be 
7417
 
            * created.
7418
 
            *
7419
 
            * @config buttons
7420
 
            * @type {Array|String}
7421
 
            * @default "none"
7422
 
            */
7423
 
            this.cfg.addProperty(DEFAULT_CONFIG.BUTTONS.key, {
7424
 
                handler: this.configButtons,
7425
 
                value: DEFAULT_CONFIG.BUTTONS.value,
7426
 
                supercedes : DEFAULT_CONFIG.BUTTONS.supercedes
7427
 
            }); 
7428
 
 
7429
 
        },
7430
 
 
7431
 
        /**
7432
 
        * Initializes the custom events for Dialog which are fired 
7433
 
        * automatically at appropriate times by the Dialog class.
7434
 
        * @method initEvents
7435
 
        */
7436
 
        initEvents: function () {
7437
 
            Dialog.superclass.initEvents.call(this);
7438
 
 
7439
 
            var SIGNATURE = CustomEvent.LIST;
7440
 
 
7441
 
            /**
7442
 
            * CustomEvent fired prior to submission
7443
 
            * @event beforeSubmitEvent
7444
 
            */ 
7445
 
            this.beforeSubmitEvent = 
7446
 
                this.createEvent(EVENT_TYPES.BEFORE_SUBMIT);
7447
 
            this.beforeSubmitEvent.signature = SIGNATURE;
7448
 
            
7449
 
            /**
7450
 
            * CustomEvent fired after submission
7451
 
            * @event submitEvent
7452
 
            */
7453
 
            this.submitEvent = this.createEvent(EVENT_TYPES.SUBMIT);
7454
 
            this.submitEvent.signature = SIGNATURE;
7455
 
        
7456
 
            /**
7457
 
            * CustomEvent fired for manual submission, before the generic submit event is fired
7458
 
            * @event manualSubmitEvent
7459
 
            */
7460
 
            this.manualSubmitEvent = 
7461
 
                this.createEvent(EVENT_TYPES.MANUAL_SUBMIT);
7462
 
            this.manualSubmitEvent.signature = SIGNATURE;
7463
 
 
7464
 
            /**
7465
 
            * CustomEvent fired after asynchronous submission, before the generic submit event is fired
7466
 
            *
7467
 
            * @event asyncSubmitEvent
7468
 
            * @param {Object} conn The connection object, returned by YAHOO.util.Connect.asyncRequest
7469
 
            */
7470
 
            this.asyncSubmitEvent = this.createEvent(EVENT_TYPES.ASYNC_SUBMIT);
7471
 
            this.asyncSubmitEvent.signature = SIGNATURE;
7472
 
 
7473
 
            /**
7474
 
            * CustomEvent fired after form-based submission, before the generic submit event is fired
7475
 
            * @event formSubmitEvent
7476
 
            */
7477
 
            this.formSubmitEvent = this.createEvent(EVENT_TYPES.FORM_SUBMIT);
7478
 
            this.formSubmitEvent.signature = SIGNATURE;
7479
 
 
7480
 
            /**
7481
 
            * CustomEvent fired after cancel
7482
 
            * @event cancelEvent
7483
 
            */
7484
 
            this.cancelEvent = this.createEvent(EVENT_TYPES.CANCEL);
7485
 
            this.cancelEvent.signature = SIGNATURE;
7486
 
        
7487
 
        },
7488
 
        
7489
 
        /**
7490
 
        * The Dialog initialization method, which is executed for Dialog and 
7491
 
        * all of its subclasses. This method is automatically called by the 
7492
 
        * constructor, and  sets up all DOM references for pre-existing markup, 
7493
 
        * and creates required markup if it is not already present.
7494
 
        * 
7495
 
        * @method init
7496
 
        * @param {String} el The element ID representing the Dialog <em>OR</em>
7497
 
        * @param {HTMLElement} el The element representing the Dialog
7498
 
        * @param {Object} userConfig The configuration object literal 
7499
 
        * containing the configuration that should be set for this Dialog. 
7500
 
        * See configuration documentation for more details.
7501
 
        */
7502
 
        init: function (el, userConfig) {
7503
 
 
7504
 
            /*
7505
 
                 Note that we don't pass the user config in here yet because 
7506
 
                 we only want it executed once, at the lowest subclass level
7507
 
            */
7508
 
 
7509
 
            Dialog.superclass.init.call(this, el/*, userConfig*/); 
7510
 
 
7511
 
            this.beforeInitEvent.fire(Dialog);
7512
 
 
7513
 
            Dom.addClass(this.element, Dialog.CSS_DIALOG);
7514
 
 
7515
 
            this.cfg.setProperty("visible", false);
7516
 
 
7517
 
            if (userConfig) {
7518
 
                this.cfg.applyConfig(userConfig, true);
7519
 
            }
7520
 
 
7521
 
            this.showEvent.subscribe(this.focusFirst, this, true);
7522
 
            this.beforeHideEvent.subscribe(this.blurButtons, this, true);
7523
 
 
7524
 
            this.subscribe("changeBody", this.registerForm);
7525
 
 
7526
 
            this.initEvent.fire(Dialog);
7527
 
        },
7528
 
 
7529
 
        /**
7530
 
        * Submits the Dialog's form depending on the value of the 
7531
 
        * "postmethod" configuration property.  <strong>Please note:
7532
 
        * </strong> As of version 2.3 this method will automatically handle 
7533
 
        * asyncronous file uploads should the Dialog instance's form contain 
7534
 
        * <code>&#60;input type="file"&#62;</code> elements.  If a Dialog 
7535
 
        * instance will be handling asyncronous file uploads, its 
7536
 
        * <code>callback</code> property will need to be setup with a 
7537
 
        * <code>upload</code> handler rather than the standard 
7538
 
        * <code>success</code> and, or <code>failure</code> handlers.  For more 
7539
 
        * information, see the <a href="http://developer.yahoo.com/yui/
7540
 
        * connection/#file">Connection Manager documenation on file uploads</a>.
7541
 
        * @method doSubmit
7542
 
        */
7543
 
        doSubmit: function () {
7544
 
 
7545
 
            var Connect = YAHOO.util.Connect,
7546
 
                oForm = this.form,
7547
 
                bUseFileUpload = false,
7548
 
                bUseSecureFileUpload = false,
7549
 
                aElements,
7550
 
                nElements,
7551
 
                i,
7552
 
                formAttrs;
7553
 
 
7554
 
            switch (this.cfg.getProperty("postmethod")) {
7555
 
 
7556
 
                case "async":
7557
 
                    aElements = oForm.elements;
7558
 
                    nElements = aElements.length;
7559
 
 
7560
 
                    if (nElements > 0) {
7561
 
                        i = nElements - 1;
7562
 
                        do {
7563
 
                            if (aElements[i].type == "file") {
7564
 
                                bUseFileUpload = true;
7565
 
                                break;
7566
 
                            }
7567
 
                        }
7568
 
                        while(i--);
7569
 
                    }
7570
 
 
7571
 
                    if (bUseFileUpload && YAHOO.env.ua.ie && this.isSecure) {
7572
 
                        bUseSecureFileUpload = true;
7573
 
                    }
7574
 
 
7575
 
                    formAttrs = this._getFormAttributes(oForm);
7576
 
 
7577
 
                    Connect.setForm(oForm, bUseFileUpload, bUseSecureFileUpload);
7578
 
 
7579
 
                    var postData = this.cfg.getProperty("postdata");
7580
 
                    var c = Connect.asyncRequest(formAttrs.method, formAttrs.action, this.callback, postData);
7581
 
 
7582
 
                    this.asyncSubmitEvent.fire(c);
7583
 
 
7584
 
                    break;
7585
 
 
7586
 
                case "form":
7587
 
                    oForm.submit();
7588
 
                    this.formSubmitEvent.fire();
7589
 
                    break;
7590
 
 
7591
 
                case "none":
7592
 
                case "manual":
7593
 
                    this.manualSubmitEvent.fire();
7594
 
                    break;
7595
 
            }
7596
 
        },
7597
 
 
7598
 
        /**
7599
 
         * Retrieves important attributes (currently method and action) from
7600
 
         * the form element, accounting for any elements which may have the same name 
7601
 
         * as the attributes. Defaults to "POST" and "" for method and action respectively
7602
 
         * if the attribute cannot be retrieved.
7603
 
         *
7604
 
         * @method _getFormAttributes
7605
 
         * @protected
7606
 
         * @param {HTMLFormElement} oForm The HTML Form element from which to retrieve the attributes
7607
 
         * @return {Object} Object literal, with method and action String properties.
7608
 
         */
7609
 
        _getFormAttributes : function(oForm){
7610
 
            var attrs = {
7611
 
                method : null,
7612
 
                action : null
7613
 
            };
7614
 
 
7615
 
            if (oForm) {
7616
 
                if (oForm.getAttributeNode) {
7617
 
                    var action = oForm.getAttributeNode("action");
7618
 
                    var method = oForm.getAttributeNode("method");
7619
 
 
7620
 
                    if (action) {
7621
 
                        attrs.action = action.value;
7622
 
                    }
7623
 
 
7624
 
                    if (method) {
7625
 
                        attrs.method = method.value;
7626
 
                    }
7627
 
 
7628
 
                } else {
7629
 
                    attrs.action = oForm.getAttribute("action");
7630
 
                    attrs.method = oForm.getAttribute("method");
7631
 
                }
7632
 
            }
7633
 
 
7634
 
            attrs.method = (Lang.isString(attrs.method) ? attrs.method : "POST").toUpperCase();
7635
 
            attrs.action = Lang.isString(attrs.action) ? attrs.action : "";
7636
 
 
7637
 
            return attrs;
7638
 
        },
7639
 
 
7640
 
        /**
7641
 
        * Prepares the Dialog's internal FORM object, creating one if one is
7642
 
        * not currently present.
7643
 
        * @method registerForm
7644
 
        */
7645
 
        registerForm: function() {
7646
 
 
7647
 
            var form = this.element.getElementsByTagName("form")[0];
7648
 
 
7649
 
            if (this.form) {
7650
 
                if (this.form == form && Dom.isAncestor(this.element, this.form)) {
7651
 
                    return;
7652
 
                } else {
7653
 
                    Event.purgeElement(this.form);
7654
 
                    this.form = null;
7655
 
                }
7656
 
            }
7657
 
 
7658
 
            if (!form) {
7659
 
                form = document.createElement("form");
7660
 
                form.name = "frm_" + this.id;
7661
 
                this.body.appendChild(form);
7662
 
            }
7663
 
 
7664
 
            if (form) {
7665
 
                this.form = form;
7666
 
                Event.on(form, "submit", this._submitHandler, this, true);
7667
 
            }
7668
 
        },
7669
 
 
7670
 
        /**
7671
 
         * Internal handler for the form submit event
7672
 
         *
7673
 
         * @method _submitHandler
7674
 
         * @protected
7675
 
         * @param {DOMEvent} e The DOM Event object
7676
 
         */
7677
 
        _submitHandler : function(e) {
7678
 
            Event.stopEvent(e);
7679
 
            this.submit();
7680
 
            this.form.blur();
7681
 
        },
7682
 
 
7683
 
        /**
7684
 
         * Sets up a tab, shift-tab loop between the first and last elements
7685
 
         * provided. NOTE: Sets up the preventBackTab and preventTabOut KeyListener
7686
 
         * instance properties, which are reset everytime this method is invoked.
7687
 
         *
7688
 
         * @method setTabLoop
7689
 
         * @param {HTMLElement} firstElement
7690
 
         * @param {HTMLElement} lastElement
7691
 
         *
7692
 
         */
7693
 
        setTabLoop : function(firstElement, lastElement) {
7694
 
 
7695
 
            firstElement = firstElement || this.firstButton;
7696
 
            lastElement = this.lastButton || lastElement;
7697
 
 
7698
 
            Dialog.superclass.setTabLoop.call(this, firstElement, lastElement);
7699
 
        },
7700
 
 
7701
 
        /**
7702
 
         * Configures instance properties, pointing to the 
7703
 
         * first and last focusable elements in the Dialog's form.
7704
 
         *
7705
 
         * @method setFirstLastFocusable
7706
 
         */
7707
 
        setFirstLastFocusable : function() {
7708
 
 
7709
 
            Dialog.superclass.setFirstLastFocusable.call(this);
7710
 
 
7711
 
            var i, l, el, elements = this.focusableElements;
7712
 
 
7713
 
            this.firstFormElement = null;
7714
 
            this.lastFormElement = null;
7715
 
 
7716
 
            if (this.form && elements && elements.length > 0) {
7717
 
                l = elements.length;
7718
 
 
7719
 
                for (i = 0; i < l; ++i) {
7720
 
                    el = elements[i];
7721
 
                    if (this.form === el.form) {
7722
 
                        this.firstFormElement = el;
7723
 
                        break;
7724
 
                    }
7725
 
                }
7726
 
 
7727
 
                for (i = l-1; i >= 0; --i) {
7728
 
                    el = elements[i];
7729
 
                    if (this.form === el.form) {
7730
 
                        this.lastFormElement = el;
7731
 
                        break;
7732
 
                    }
7733
 
                }
7734
 
            }
7735
 
        },
7736
 
 
7737
 
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
7738
 
        /**
7739
 
        * The default event handler fired when the "close" property is 
7740
 
        * changed. The method controls the appending or hiding of the close
7741
 
        * icon at the top right of the Dialog.
7742
 
        * @method configClose
7743
 
        * @param {String} type The CustomEvent type (usually the property name)
7744
 
        * @param {Object[]} args The CustomEvent arguments. For 
7745
 
        * configuration handlers, args[0] will equal the newly applied value 
7746
 
        * for the property.
7747
 
        * @param {Object} obj The scope object. For configuration handlers, 
7748
 
        * this will usually equal the owner.
7749
 
        */
7750
 
        configClose: function (type, args, obj) {
7751
 
            Dialog.superclass.configClose.apply(this, arguments);
7752
 
        },
7753
 
 
7754
 
        /**
7755
 
         * Event handler for the close icon
7756
 
         * 
7757
 
         * @method _doClose
7758
 
         * @protected
7759
 
         * 
7760
 
         * @param {DOMEvent} e
7761
 
         */
7762
 
         _doClose : function(e) {
7763
 
            Event.preventDefault(e);
7764
 
            this.cancel();
7765
 
        },
7766
 
 
7767
 
        /**
7768
 
        * The default event handler for the "buttons" configuration property
7769
 
        * @method configButtons
7770
 
        * @param {String} type The CustomEvent type (usually the property name)
7771
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
7772
 
        * handlers, args[0] will equal the newly applied value for the property.
7773
 
        * @param {Object} obj The scope object. For configuration handlers, 
7774
 
        * this will usually equal the owner.
7775
 
        */
7776
 
        configButtons: function (type, args, obj) {
7777
 
 
7778
 
            var Button = YAHOO.widget.Button,
7779
 
                aButtons = args[0],
7780
 
                oInnerElement = this.innerElement,
7781
 
                oButton,
7782
 
                oButtonEl,
7783
 
                oYUIButton,
7784
 
                nButtons,
7785
 
                oSpan,
7786
 
                oFooter,
7787
 
                i;
7788
 
 
7789
 
            removeButtonEventHandlers.call(this);
7790
 
 
7791
 
            this._aButtons = null;
7792
 
 
7793
 
            if (Lang.isArray(aButtons)) {
7794
 
 
7795
 
                oSpan = document.createElement("span");
7796
 
                oSpan.className = "button-group";
7797
 
                nButtons = aButtons.length;
7798
 
 
7799
 
                this._aButtons = [];
7800
 
                this.defaultHtmlButton = null;
7801
 
 
7802
 
                for (i = 0; i < nButtons; i++) {
7803
 
                    oButton = aButtons[i];
7804
 
 
7805
 
                    if (Button) {
7806
 
                        oYUIButton = new Button({ label: oButton.text});
7807
 
                        oYUIButton.appendTo(oSpan);
7808
 
 
7809
 
                        oButtonEl = oYUIButton.get("element");
7810
 
 
7811
 
                        if (oButton.isDefault) {
7812
 
                            oYUIButton.addClass("default");
7813
 
                            this.defaultHtmlButton = oButtonEl;
7814
 
                        }
7815
 
 
7816
 
                        if (Lang.isFunction(oButton.handler)) {
7817
 
 
7818
 
                            oYUIButton.set("onclick", { 
7819
 
                                fn: oButton.handler, 
7820
 
                                obj: this, 
7821
 
                                scope: this 
7822
 
                            });
7823
 
 
7824
 
                        } else if (Lang.isObject(oButton.handler) && Lang.isFunction(oButton.handler.fn)) {
7825
 
 
7826
 
                            oYUIButton.set("onclick", { 
7827
 
                                fn: oButton.handler.fn, 
7828
 
                                obj: ((!Lang.isUndefined(oButton.handler.obj)) ? oButton.handler.obj : this), 
7829
 
                                scope: (oButton.handler.scope || this) 
7830
 
                            });
7831
 
 
7832
 
                        }
7833
 
 
7834
 
                        this._aButtons[this._aButtons.length] = oYUIButton;
7835
 
 
7836
 
                    } else {
7837
 
 
7838
 
                        oButtonEl = document.createElement("button");
7839
 
                        oButtonEl.setAttribute("type", "button");
7840
 
 
7841
 
                        if (oButton.isDefault) {
7842
 
                            oButtonEl.className = "default";
7843
 
                            this.defaultHtmlButton = oButtonEl;
7844
 
                        }
7845
 
 
7846
 
                        oButtonEl.innerHTML = oButton.text;
7847
 
 
7848
 
                        if (Lang.isFunction(oButton.handler)) {
7849
 
                            Event.on(oButtonEl, "click", oButton.handler, this, true);
7850
 
                        } else if (Lang.isObject(oButton.handler) && 
7851
 
                            Lang.isFunction(oButton.handler.fn)) {
7852
 
    
7853
 
                            Event.on(oButtonEl, "click", 
7854
 
                                oButton.handler.fn, 
7855
 
                                ((!Lang.isUndefined(oButton.handler.obj)) ? oButton.handler.obj : this), 
7856
 
                                (oButton.handler.scope || this));
7857
 
                        }
7858
 
 
7859
 
                        oSpan.appendChild(oButtonEl);
7860
 
                        this._aButtons[this._aButtons.length] = oButtonEl;
7861
 
                    }
7862
 
 
7863
 
                    oButton.htmlButton = oButtonEl;
7864
 
 
7865
 
                    if (i === 0) {
7866
 
                        this.firstButton = oButtonEl;
7867
 
                    }
7868
 
 
7869
 
                    if (i == (nButtons - 1)) {
7870
 
                        this.lastButton = oButtonEl;
7871
 
                    }
7872
 
                }
7873
 
 
7874
 
                this.setFooter(oSpan);
7875
 
 
7876
 
                oFooter = this.footer;
7877
 
 
7878
 
                if (Dom.inDocument(this.element) && !Dom.isAncestor(oInnerElement, oFooter)) {
7879
 
                    oInnerElement.appendChild(oFooter);
7880
 
                }
7881
 
 
7882
 
                this.buttonSpan = oSpan;
7883
 
 
7884
 
            } else { // Do cleanup
7885
 
                oSpan = this.buttonSpan;
7886
 
                oFooter = this.footer;
7887
 
                if (oSpan && oFooter) {
7888
 
                    oFooter.removeChild(oSpan);
7889
 
                    this.buttonSpan = null;
7890
 
                    this.firstButton = null;
7891
 
                    this.lastButton = null;
7892
 
                    this.defaultHtmlButton = null;
7893
 
                }
7894
 
            }
7895
 
 
7896
 
            this.changeContentEvent.fire();
7897
 
        },
7898
 
 
7899
 
        /**
7900
 
        * @method getButtons
7901
 
        * @description Returns an array containing each of the Dialog's 
7902
 
        * buttons, by default an array of HTML <code>&#60;BUTTON&#62;</code> 
7903
 
        * elements.  If the Dialog's buttons were created using the 
7904
 
        * YAHOO.widget.Button class (via the inclusion of the optional Button 
7905
 
        * dependancy on the page), an array of YAHOO.widget.Button instances 
7906
 
        * is returned.
7907
 
        * @return {Array}
7908
 
        */
7909
 
        getButtons: function () {
7910
 
            return this._aButtons || null;
7911
 
        },
7912
 
 
7913
 
        /**
7914
 
         * <p>
7915
 
         * Sets focus to the first focusable element in the Dialog's form if found, 
7916
 
         * else, the default button if found, else the first button defined via the 
7917
 
         * "buttons" configuration property.
7918
 
         * </p>
7919
 
         * <p>
7920
 
         * This method is invoked when the Dialog is made visible.
7921
 
         * </p>
7922
 
         * @method focusFirst
7923
 
         */
7924
 
        focusFirst: function (type, args, obj) {
7925
 
 
7926
 
            var el = this.firstFormElement;
7927
 
 
7928
 
            if (args && args[1]) {
7929
 
                Event.stopEvent(args[1]);
7930
 
            }
7931
 
 
7932
 
            if (el) {
7933
 
                try {
7934
 
                    el.focus();
7935
 
                } catch(oException) {
7936
 
                    // Ignore
7937
 
                }
7938
 
            } else {
7939
 
                if (this.defaultHtmlButton) {
7940
 
                    this.focusDefaultButton();
7941
 
                } else {
7942
 
                    this.focusFirstButton();
7943
 
                }
7944
 
            }
7945
 
        },
7946
 
 
7947
 
        /**
7948
 
        * Sets focus to the last element in the Dialog's form or the last 
7949
 
        * button defined via the "buttons" configuration property.
7950
 
        * @method focusLast
7951
 
        */
7952
 
        focusLast: function (type, args, obj) {
7953
 
 
7954
 
            var aButtons = this.cfg.getProperty("buttons"),
7955
 
                el = this.lastFormElement;
7956
 
 
7957
 
            if (args && args[1]) {
7958
 
                Event.stopEvent(args[1]);
7959
 
            }
7960
 
 
7961
 
            if (aButtons && Lang.isArray(aButtons)) {
7962
 
                this.focusLastButton();
7963
 
            } else {
7964
 
                if (el) {
7965
 
                    try {
7966
 
                        el.focus();
7967
 
                    } catch(oException) {
7968
 
                        // Ignore
7969
 
                    }
7970
 
                }
7971
 
            }
7972
 
        },
7973
 
 
7974
 
        /**
7975
 
         * Helper method to normalize button references. It either returns the 
7976
 
         * YUI Button instance for the given element if found,
7977
 
         * or the passes back the HTMLElement reference if a corresponding YUI Button
7978
 
         * reference is not found or YAHOO.widget.Button does not exist on the page.
7979
 
         *
7980
 
         * @method _getButton
7981
 
         * @private
7982
 
         * @param {HTMLElement} button
7983
 
         * @return {YAHOO.widget.Button|HTMLElement}
7984
 
         */
7985
 
        _getButton : function(button) {
7986
 
            var Button = YAHOO.widget.Button;
7987
 
 
7988
 
            // If we have an HTML button and YUI Button is on the page, 
7989
 
            // get the YUI Button reference if available.
7990
 
            if (Button && button && button.nodeName && button.id) {
7991
 
                button = Button.getButton(button.id) || button;
7992
 
            }
7993
 
 
7994
 
            return button;
7995
 
        },
7996
 
 
7997
 
        /**
7998
 
        * Sets the focus to the button that is designated as the default via 
7999
 
        * the "buttons" configuration property. By default, this method is 
8000
 
        * called when the Dialog is made visible.
8001
 
        * @method focusDefaultButton
8002
 
        */
8003
 
        focusDefaultButton: function () {
8004
 
            var button = this._getButton(this.defaultHtmlButton);
8005
 
            if (button) {
8006
 
                /*
8007
 
                    Place the call to the "focus" method inside a try/catch
8008
 
                    block to prevent IE from throwing JavaScript errors if
8009
 
                    the element is disabled or hidden.
8010
 
                */
8011
 
                try {
8012
 
                    button.focus();
8013
 
                } catch(oException) {
8014
 
                }
8015
 
            }
8016
 
        },
8017
 
 
8018
 
        /**
8019
 
        * Blurs all the buttons defined via the "buttons" 
8020
 
        * configuration property.
8021
 
        * @method blurButtons
8022
 
        */
8023
 
        blurButtons: function () {
8024
 
            
8025
 
            var aButtons = this.cfg.getProperty("buttons"),
8026
 
                nButtons,
8027
 
                oButton,
8028
 
                oElement,
8029
 
                i;
8030
 
 
8031
 
            if (aButtons && Lang.isArray(aButtons)) {
8032
 
                nButtons = aButtons.length;
8033
 
                if (nButtons > 0) {
8034
 
                    i = (nButtons - 1);
8035
 
                    do {
8036
 
                        oButton = aButtons[i];
8037
 
                        if (oButton) {
8038
 
                            oElement = this._getButton(oButton.htmlButton);
8039
 
                            if (oElement) {
8040
 
                                /*
8041
 
                                    Place the call to the "blur" method inside  
8042
 
                                    a try/catch block to prevent IE from  
8043
 
                                    throwing JavaScript errors if the element 
8044
 
                                    is disabled or hidden.
8045
 
                                */
8046
 
                                try {
8047
 
                                    oElement.blur();
8048
 
                                } catch(oException) {
8049
 
                                    // ignore
8050
 
                                }
8051
 
                            }
8052
 
                        }
8053
 
                    } while(i--);
8054
 
                }
8055
 
            }
8056
 
        },
8057
 
 
8058
 
        /**
8059
 
        * Sets the focus to the first button created via the "buttons"
8060
 
        * configuration property.
8061
 
        * @method focusFirstButton
8062
 
        */
8063
 
        focusFirstButton: function () {
8064
 
 
8065
 
            var aButtons = this.cfg.getProperty("buttons"),
8066
 
                oButton,
8067
 
                oElement;
8068
 
 
8069
 
            if (aButtons && Lang.isArray(aButtons)) {
8070
 
                oButton = aButtons[0];
8071
 
                if (oButton) {
8072
 
                    oElement = this._getButton(oButton.htmlButton);
8073
 
                    if (oElement) {
8074
 
                        /*
8075
 
                            Place the call to the "focus" method inside a 
8076
 
                            try/catch block to prevent IE from throwing 
8077
 
                            JavaScript errors if the element is disabled 
8078
 
                            or hidden.
8079
 
                        */
8080
 
                        try {
8081
 
                            oElement.focus();
8082
 
                        } catch(oException) {
8083
 
                            // ignore
8084
 
                        }
8085
 
                    }
8086
 
                }
8087
 
            }
8088
 
        },
8089
 
 
8090
 
        /**
8091
 
        * Sets the focus to the last button created via the "buttons" 
8092
 
        * configuration property.
8093
 
        * @method focusLastButton
8094
 
        */
8095
 
        focusLastButton: function () {
8096
 
 
8097
 
            var aButtons = this.cfg.getProperty("buttons"),
8098
 
                nButtons,
8099
 
                oButton,
8100
 
                oElement;
8101
 
 
8102
 
            if (aButtons && Lang.isArray(aButtons)) {
8103
 
                nButtons = aButtons.length;
8104
 
                if (nButtons > 0) {
8105
 
                    oButton = aButtons[(nButtons - 1)];
8106
 
 
8107
 
                    if (oButton) {
8108
 
                        oElement = this._getButton(oButton.htmlButton);
8109
 
                        if (oElement) {
8110
 
                            /*
8111
 
                                Place the call to the "focus" method inside a 
8112
 
                                try/catch block to prevent IE from throwing 
8113
 
                                JavaScript errors if the element is disabled
8114
 
                                or hidden.
8115
 
                            */
8116
 
        
8117
 
                            try {
8118
 
                                oElement.focus();
8119
 
                            } catch(oException) {
8120
 
                                // Ignore
8121
 
                            }
8122
 
                        }
8123
 
                    }
8124
 
                }
8125
 
            }
8126
 
        },
8127
 
 
8128
 
        /**
8129
 
        * The default event handler for the "postmethod" configuration property
8130
 
        * @method configPostMethod
8131
 
        * @param {String} type The CustomEvent type (usually the property name)
8132
 
        * @param {Object[]} args The CustomEvent arguments. For 
8133
 
        * configuration handlers, args[0] will equal the newly applied value 
8134
 
        * for the property.
8135
 
        * @param {Object} obj The scope object. For configuration handlers, 
8136
 
        * this will usually equal the owner.
8137
 
        */
8138
 
        configPostMethod: function (type, args, obj) {
8139
 
            this.registerForm();
8140
 
        },
8141
 
 
8142
 
        // END BUILT-IN PROPERTY EVENT HANDLERS //
8143
 
        
8144
 
        /**
8145
 
        * Built-in function hook for writing a validation function that will 
8146
 
        * be checked for a "true" value prior to a submit. This function, as 
8147
 
        * implemented by default, always returns true, so it should be 
8148
 
        * overridden if validation is necessary.
8149
 
        * @method validate
8150
 
        */
8151
 
        validate: function () {
8152
 
            return true;
8153
 
        },
8154
 
        
8155
 
        /**
8156
 
        * Executes a submit of the Dialog if validation 
8157
 
        * is successful. By default the Dialog is hidden
8158
 
        * after submission, but you can set the "hideaftersubmit"
8159
 
        * configuration property to false, to prevent the Dialog
8160
 
        * from being hidden.
8161
 
        * 
8162
 
        * @method submit
8163
 
        */
8164
 
        submit: function () {
8165
 
            if (this.validate()) {
8166
 
                this.beforeSubmitEvent.fire();
8167
 
                this.doSubmit();
8168
 
                this.submitEvent.fire();
8169
 
 
8170
 
                if (this.cfg.getProperty("hideaftersubmit")) {
8171
 
                    this.hide();
8172
 
                }
8173
 
 
8174
 
                return true;
8175
 
            } else {
8176
 
                return false;
8177
 
            }
8178
 
        },
8179
 
 
8180
 
        /**
8181
 
        * Executes the cancel of the Dialog followed by a hide.
8182
 
        * @method cancel
8183
 
        */
8184
 
        cancel: function () {
8185
 
            this.cancelEvent.fire();
8186
 
            this.hide();
8187
 
        },
8188
 
        
8189
 
        /**
8190
 
        * Returns a JSON-compatible data structure representing the data 
8191
 
        * currently contained in the form.
8192
 
        * @method getData
8193
 
        * @return {Object} A JSON object reprsenting the data of the 
8194
 
        * current form.
8195
 
        */
8196
 
        getData: function () {
8197
 
 
8198
 
            var oForm = this.form,
8199
 
                aElements,
8200
 
                nTotalElements,
8201
 
                oData,
8202
 
                sName,
8203
 
                oElement,
8204
 
                nElements,
8205
 
                sType,
8206
 
                sTagName,
8207
 
                aOptions,
8208
 
                nOptions,
8209
 
                aValues,
8210
 
                oOption,
8211
 
                sValue,
8212
 
                oRadio,
8213
 
                oCheckbox,
8214
 
                i,
8215
 
                n;    
8216
 
    
8217
 
            function isFormElement(p_oElement) {
8218
 
                var sTag = p_oElement.tagName.toUpperCase();
8219
 
                return ((sTag == "INPUT" || sTag == "TEXTAREA" || 
8220
 
                        sTag == "SELECT") && p_oElement.name == sName);
8221
 
            }
8222
 
 
8223
 
            if (oForm) {
8224
 
 
8225
 
                aElements = oForm.elements;
8226
 
                nTotalElements = aElements.length;
8227
 
                oData = {};
8228
 
 
8229
 
                for (i = 0; i < nTotalElements; i++) {
8230
 
                    sName = aElements[i].name;
8231
 
 
8232
 
                    /*
8233
 
                        Using "Dom.getElementsBy" to safeguard user from JS 
8234
 
                        errors that result from giving a form field (or set of 
8235
 
                        fields) the same name as a native method of a form 
8236
 
                        (like "submit") or a DOM collection (such as the "item"
8237
 
                        method). Originally tried accessing fields via the 
8238
 
                        "namedItem" method of the "element" collection, but 
8239
 
                        discovered that it won't return a collection of fields 
8240
 
                        in Gecko.
8241
 
                    */
8242
 
 
8243
 
                    oElement = Dom.getElementsBy(isFormElement, "*", oForm);
8244
 
                    nElements = oElement.length;
8245
 
 
8246
 
                    if (nElements > 0) {
8247
 
                        if (nElements == 1) {
8248
 
                            oElement = oElement[0];
8249
 
 
8250
 
                            sType = oElement.type;
8251
 
                            sTagName = oElement.tagName.toUpperCase();
8252
 
 
8253
 
                            switch (sTagName) {
8254
 
                                case "INPUT":
8255
 
                                    if (sType == "checkbox") {
8256
 
                                        oData[sName] = oElement.checked;
8257
 
                                    } else if (sType != "radio") {
8258
 
                                        oData[sName] = oElement.value;
8259
 
                                    }
8260
 
                                    break;
8261
 
 
8262
 
                                case "TEXTAREA":
8263
 
                                    oData[sName] = oElement.value;
8264
 
                                    break;
8265
 
    
8266
 
                                case "SELECT":
8267
 
                                    aOptions = oElement.options;
8268
 
                                    nOptions = aOptions.length;
8269
 
                                    aValues = [];
8270
 
    
8271
 
                                    for (n = 0; n < nOptions; n++) {
8272
 
                                        oOption = aOptions[n];
8273
 
    
8274
 
                                        if (oOption.selected) {
8275
 
                                            sValue = oOption.value;
8276
 
                                            if (!sValue || sValue === "") {
8277
 
                                                sValue = oOption.text;
8278
 
                                            }
8279
 
                                            aValues[aValues.length] = sValue;
8280
 
                                        }
8281
 
                                    }
8282
 
                                    oData[sName] = aValues;
8283
 
                                    break;
8284
 
                            }
8285
 
        
8286
 
                        } else {
8287
 
                            sType = oElement[0].type;
8288
 
                            switch (sType) {
8289
 
                                case "radio":
8290
 
                                    for (n = 0; n < nElements; n++) {
8291
 
                                        oRadio = oElement[n];
8292
 
                                        if (oRadio.checked) {
8293
 
                                            oData[sName] = oRadio.value;
8294
 
                                            break;
8295
 
                                        }
8296
 
                                    }
8297
 
                                    break;
8298
 
        
8299
 
                                case "checkbox":
8300
 
                                    aValues = [];
8301
 
                                    for (n = 0; n < nElements; n++) {
8302
 
                                        oCheckbox = oElement[n];
8303
 
                                        if (oCheckbox.checked) {
8304
 
                                            aValues[aValues.length] =  oCheckbox.value;
8305
 
                                        }
8306
 
                                    }
8307
 
                                    oData[sName] = aValues;
8308
 
                                    break;
8309
 
                            }
8310
 
                        }
8311
 
                    }
8312
 
                }
8313
 
            }
8314
 
 
8315
 
            return oData;
8316
 
        },
8317
 
 
8318
 
        /**
8319
 
        * Removes the Panel element from the DOM and sets all child elements 
8320
 
        * to null.
8321
 
        * @method destroy
8322
 
        */
8323
 
        destroy: function () {
8324
 
            removeButtonEventHandlers.call(this);
8325
 
 
8326
 
            this._aButtons = null;
8327
 
 
8328
 
            var aForms = this.element.getElementsByTagName("form"),
8329
 
                oForm;
8330
 
 
8331
 
            if (aForms.length > 0) {
8332
 
                oForm = aForms[0];
8333
 
 
8334
 
                if (oForm) {
8335
 
                    Event.purgeElement(oForm);
8336
 
                    if (oForm.parentNode) {
8337
 
                        oForm.parentNode.removeChild(oForm);
8338
 
                    }
8339
 
                    this.form = null;
8340
 
                }
8341
 
            }
8342
 
            Dialog.superclass.destroy.call(this);
8343
 
        },
8344
 
 
8345
 
        /**
8346
 
        * Returns a string representation of the object.
8347
 
        * @method toString
8348
 
        * @return {String} The string representation of the Dialog
8349
 
        */
8350
 
        toString: function () {
8351
 
            return "Dialog " + this.id;
8352
 
        }
8353
 
    
8354
 
    });
8355
 
 
8356
 
}());
8357
 
 
8358
 
(function () {
8359
 
 
8360
 
    /**
8361
 
    * SimpleDialog is a simple implementation of Dialog that can be used to 
8362
 
    * submit a single value. Forms can be processed in 3 ways -- via an 
8363
 
    * asynchronous Connection utility call, a simple form POST or GET, 
8364
 
    * or manually.
8365
 
    * @namespace YAHOO.widget
8366
 
    * @class SimpleDialog
8367
 
    * @extends YAHOO.widget.Dialog
8368
 
    * @constructor
8369
 
    * @param {String} el The element ID representing the SimpleDialog 
8370
 
    * <em>OR</em>
8371
 
    * @param {HTMLElement} el The element representing the SimpleDialog
8372
 
    * @param {Object} userConfig The configuration object literal containing 
8373
 
    * the configuration that should be set for this SimpleDialog. See 
8374
 
    * configuration documentation for more details.
8375
 
    */
8376
 
    YAHOO.widget.SimpleDialog = function (el, userConfig) {
8377
 
    
8378
 
        YAHOO.widget.SimpleDialog.superclass.constructor.call(this, 
8379
 
            el, userConfig);
8380
 
    
8381
 
    };
8382
 
 
8383
 
    var Dom = YAHOO.util.Dom,
8384
 
        SimpleDialog = YAHOO.widget.SimpleDialog,
8385
 
    
8386
 
        /**
8387
 
        * Constant representing the SimpleDialog's configuration properties
8388
 
        * @property DEFAULT_CONFIG
8389
 
        * @private
8390
 
        * @final
8391
 
        * @type Object
8392
 
        */
8393
 
        DEFAULT_CONFIG = {
8394
 
        
8395
 
            "ICON": { 
8396
 
                key: "icon", 
8397
 
                value: "none", 
8398
 
                suppressEvent: true  
8399
 
            },
8400
 
        
8401
 
            "TEXT": { 
8402
 
                key: "text", 
8403
 
                value: "", 
8404
 
                suppressEvent: true, 
8405
 
                supercedes: ["icon"] 
8406
 
            }
8407
 
        
8408
 
        };
8409
 
 
8410
 
    /**
8411
 
    * Constant for the standard network icon for a blocking action
8412
 
    * @property YAHOO.widget.SimpleDialog.ICON_BLOCK
8413
 
    * @static
8414
 
    * @final
8415
 
    * @type String
8416
 
    */
8417
 
    SimpleDialog.ICON_BLOCK = "blckicon";
8418
 
    
8419
 
    /**
8420
 
    * Constant for the standard network icon for alarm
8421
 
    * @property YAHOO.widget.SimpleDialog.ICON_ALARM
8422
 
    * @static
8423
 
    * @final
8424
 
    * @type String
8425
 
    */
8426
 
    SimpleDialog.ICON_ALARM = "alrticon";
8427
 
    
8428
 
    /**
8429
 
    * Constant for the standard network icon for help
8430
 
    * @property YAHOO.widget.SimpleDialog.ICON_HELP
8431
 
    * @static
8432
 
    * @final
8433
 
    * @type String
8434
 
    */
8435
 
    SimpleDialog.ICON_HELP  = "hlpicon";
8436
 
    
8437
 
    /**
8438
 
    * Constant for the standard network icon for info
8439
 
    * @property YAHOO.widget.SimpleDialog.ICON_INFO
8440
 
    * @static
8441
 
    * @final
8442
 
    * @type String
8443
 
    */
8444
 
    SimpleDialog.ICON_INFO  = "infoicon";
8445
 
    
8446
 
    /**
8447
 
    * Constant for the standard network icon for warn
8448
 
    * @property YAHOO.widget.SimpleDialog.ICON_WARN
8449
 
    * @static
8450
 
    * @final
8451
 
    * @type String
8452
 
    */
8453
 
    SimpleDialog.ICON_WARN  = "warnicon";
8454
 
    
8455
 
    /**
8456
 
    * Constant for the standard network icon for a tip
8457
 
    * @property YAHOO.widget.SimpleDialog.ICON_TIP
8458
 
    * @static
8459
 
    * @final
8460
 
    * @type String
8461
 
    */
8462
 
    SimpleDialog.ICON_TIP   = "tipicon";
8463
 
 
8464
 
    /**
8465
 
    * Constant representing the name of the CSS class applied to the element 
8466
 
    * created by the "icon" configuration property.
8467
 
    * @property YAHOO.widget.SimpleDialog.ICON_CSS_CLASSNAME
8468
 
    * @static
8469
 
    * @final
8470
 
    * @type String
8471
 
    */
8472
 
    SimpleDialog.ICON_CSS_CLASSNAME = "yui-icon";
8473
 
    
8474
 
    /**
8475
 
    * Constant representing the default CSS class used for a SimpleDialog
8476
 
    * @property YAHOO.widget.SimpleDialog.CSS_SIMPLEDIALOG
8477
 
    * @static
8478
 
    * @final
8479
 
    * @type String
8480
 
    */
8481
 
    SimpleDialog.CSS_SIMPLEDIALOG = "yui-simple-dialog";
8482
 
 
8483
 
    
8484
 
    YAHOO.extend(SimpleDialog, YAHOO.widget.Dialog, {
8485
 
    
8486
 
        /**
8487
 
        * Initializes the class's configurable properties which can be changed 
8488
 
        * using the SimpleDialog's Config object (cfg).
8489
 
        * @method initDefaultConfig
8490
 
        */
8491
 
        initDefaultConfig: function () {
8492
 
        
8493
 
            SimpleDialog.superclass.initDefaultConfig.call(this);
8494
 
        
8495
 
            // Add dialog config properties //
8496
 
        
8497
 
            /**
8498
 
            * Sets the informational icon for the SimpleDialog
8499
 
            * @config icon
8500
 
            * @type String
8501
 
            * @default "none"
8502
 
            */
8503
 
            this.cfg.addProperty(DEFAULT_CONFIG.ICON.key, {
8504
 
                handler: this.configIcon,
8505
 
                value: DEFAULT_CONFIG.ICON.value,
8506
 
                suppressEvent: DEFAULT_CONFIG.ICON.suppressEvent
8507
 
            });
8508
 
        
8509
 
            /**
8510
 
            * Sets the text for the SimpleDialog
8511
 
            * @config text
8512
 
            * @type String
8513
 
            * @default ""
8514
 
            */
8515
 
            this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, { 
8516
 
                handler: this.configText, 
8517
 
                value: DEFAULT_CONFIG.TEXT.value, 
8518
 
                suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent, 
8519
 
                supercedes: DEFAULT_CONFIG.TEXT.supercedes 
8520
 
            });
8521
 
        
8522
 
        },
8523
 
        
8524
 
        
8525
 
        /**
8526
 
        * The SimpleDialog initialization method, which is executed for 
8527
 
        * SimpleDialog and all of its subclasses. This method is automatically 
8528
 
        * called by the constructor, and  sets up all DOM references for 
8529
 
        * pre-existing markup, and creates required markup if it is not 
8530
 
        * already present.
8531
 
        * @method init
8532
 
        * @param {String} el The element ID representing the SimpleDialog 
8533
 
        * <em>OR</em>
8534
 
        * @param {HTMLElement} el The element representing the SimpleDialog
8535
 
        * @param {Object} userConfig The configuration object literal 
8536
 
        * containing the configuration that should be set for this 
8537
 
        * SimpleDialog. See configuration documentation for more details.
8538
 
        */
8539
 
        init: function (el, userConfig) {
8540
 
 
8541
 
            /*
8542
 
                Note that we don't pass the user config in here yet because we 
8543
 
                only want it executed once, at the lowest subclass level
8544
 
            */
8545
 
 
8546
 
            SimpleDialog.superclass.init.call(this, el/*, userConfig*/);
8547
 
        
8548
 
            this.beforeInitEvent.fire(SimpleDialog);
8549
 
        
8550
 
            Dom.addClass(this.element, SimpleDialog.CSS_SIMPLEDIALOG);
8551
 
        
8552
 
            this.cfg.queueProperty("postmethod", "manual");
8553
 
        
8554
 
            if (userConfig) {
8555
 
                this.cfg.applyConfig(userConfig, true);
8556
 
            }
8557
 
        
8558
 
            this.beforeRenderEvent.subscribe(function () {
8559
 
                if (! this.body) {
8560
 
                    this.setBody("");
8561
 
                }
8562
 
            }, this, true);
8563
 
        
8564
 
            this.initEvent.fire(SimpleDialog);
8565
 
        
8566
 
        },
8567
 
        
8568
 
        /**
8569
 
        * Prepares the SimpleDialog's internal FORM object, creating one if one 
8570
 
        * is not currently present, and adding the value hidden field.
8571
 
        * @method registerForm
8572
 
        */
8573
 
        registerForm: function () {
8574
 
 
8575
 
            SimpleDialog.superclass.registerForm.call(this);
8576
 
 
8577
 
            this.form.innerHTML += "<input type=\"hidden\" name=\"" + 
8578
 
                this.id + "\" value=\"\"/>";
8579
 
 
8580
 
        },
8581
 
        
8582
 
        // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
8583
 
        
8584
 
        /**
8585
 
        * Fired when the "icon" property is set.
8586
 
        * @method configIcon
8587
 
        * @param {String} type The CustomEvent type (usually the property name)
8588
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
8589
 
        * handlers, args[0] will equal the newly applied value for the property.
8590
 
        * @param {Object} obj The scope object. For configuration handlers, 
8591
 
        * this will usually equal the owner.
8592
 
        */
8593
 
        configIcon: function (type,args,obj) {
8594
 
        
8595
 
            var sIcon = args[0],
8596
 
                oBody = this.body,
8597
 
                sCSSClass = SimpleDialog.ICON_CSS_CLASSNAME,
8598
 
                oIcon,
8599
 
                oIconParent;
8600
 
        
8601
 
            if (sIcon && sIcon != "none") {
8602
 
 
8603
 
                oIcon = Dom.getElementsByClassName(sCSSClass, "*" , oBody);
8604
 
 
8605
 
                if (oIcon) {
8606
 
 
8607
 
                    oIconParent = oIcon.parentNode;
8608
 
                    
8609
 
                    if (oIconParent) {
8610
 
                    
8611
 
                        oIconParent.removeChild(oIcon);
8612
 
                        
8613
 
                        oIcon = null;
8614
 
                    
8615
 
                    }
8616
 
 
8617
 
                }
8618
 
 
8619
 
 
8620
 
                if (sIcon.indexOf(".") == -1) {
8621
 
 
8622
 
                    oIcon = document.createElement("span");
8623
 
                    oIcon.className = (sCSSClass + " " + sIcon);
8624
 
                    oIcon.innerHTML = "&#160;";
8625
 
 
8626
 
                } else {
8627
 
 
8628
 
                    oIcon = document.createElement("img");
8629
 
                    oIcon.src = (this.imageRoot + sIcon);
8630
 
                    oIcon.className = sCSSClass;
8631
 
 
8632
 
                }
8633
 
                
8634
 
 
8635
 
                if (oIcon) {
8636
 
                
8637
 
                    oBody.insertBefore(oIcon, oBody.firstChild);
8638
 
                
8639
 
                }
8640
 
 
8641
 
            }
8642
 
 
8643
 
        },
8644
 
 
8645
 
        /**
8646
 
        * Fired when the "text" property is set.
8647
 
        * @method configText
8648
 
        * @param {String} type The CustomEvent type (usually the property name)
8649
 
        * @param {Object[]} args The CustomEvent arguments. For configuration 
8650
 
        * handlers, args[0] will equal the newly applied value for the property.
8651
 
        * @param {Object} obj The scope object. For configuration handlers, 
8652
 
        * this will usually equal the owner.
8653
 
        */
8654
 
        configText: function (type,args,obj) {
8655
 
            var text = args[0];
8656
 
            if (text) {
8657
 
                this.setBody(text);
8658
 
                this.cfg.refireEvent("icon");
8659
 
            }
8660
 
        },
8661
 
        
8662
 
        // END BUILT-IN PROPERTY EVENT HANDLERS //
8663
 
        
8664
 
        /**
8665
 
        * Returns a string representation of the object.
8666
 
        * @method toString
8667
 
        * @return {String} The string representation of the SimpleDialog
8668
 
        */
8669
 
        toString: function () {
8670
 
            return "SimpleDialog " + this.id;
8671
 
        }
8672
 
 
8673
 
        /**
8674
 
        * <p>
8675
 
        * Sets the SimpleDialog's body content to the HTML specified. 
8676
 
        * If no body is present, one will be automatically created. 
8677
 
        * An empty string can be passed to the method to clear the contents of the body.
8678
 
        * </p>
8679
 
        * <p><strong>NOTE:</strong> SimpleDialog provides the <a href="#config_text">text</a>
8680
 
        * and <a href="#config_icon">icon</a> configuration properties to set the contents
8681
 
        * of it's body element in accordance with the UI design for a SimpleDialog (an 
8682
 
        * icon and message text). Calling setBody on the SimpleDialog will not enforce this 
8683
 
        * UI design constraint and will replace the entire contents of the SimpleDialog body. 
8684
 
        * It should only be used if you wish the replace the default icon/text body structure 
8685
 
        * of a SimpleDialog with your own custom markup.</p>
8686
 
        * 
8687
 
        * @method setBody
8688
 
        * @param {String} bodyContent The HTML used to set the body. 
8689
 
        * As a convenience, non HTMLElement objects can also be passed into 
8690
 
        * the method, and will be treated as strings, with the body innerHTML
8691
 
        * set to their default toString implementations.
8692
 
        * <em>OR</em>
8693
 
        * @param {HTMLElement} bodyContent The HTMLElement to add as the first and only child of the body element.
8694
 
        * <em>OR</em>
8695
 
        * @param {DocumentFragment} bodyContent The document fragment 
8696
 
        * containing elements which are to be added to the body
8697
 
        */
8698
 
    });
8699
 
 
8700
 
}());
8701
 
 
8702
 
(function () {
8703
 
 
8704
 
    /**
8705
 
    * ContainerEffect encapsulates animation transitions that are executed when 
8706
 
    * an Overlay is shown or hidden.
8707
 
    * @namespace YAHOO.widget
8708
 
    * @class ContainerEffect
8709
 
    * @constructor
8710
 
    * @param {YAHOO.widget.Overlay} overlay The Overlay that the animation 
8711
 
    * should be associated with
8712
 
    * @param {Object} attrIn The object literal representing the animation 
8713
 
    * arguments to be used for the animate-in transition. The arguments for 
8714
 
    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
8715
 
    * duration(Number), and method(i.e. Easing.easeIn).
8716
 
    * @param {Object} attrOut The object literal representing the animation 
8717
 
    * arguments to be used for the animate-out transition. The arguments for  
8718
 
    * this literal are: attributes(object, see YAHOO.util.Anim for description), 
8719
 
    * duration(Number), and method(i.e. Easing.easeIn).
8720
 
    * @param {HTMLElement} targetElement Optional. The target element that  
8721
 
    * should be animated during the transition. Defaults to overlay.element.
8722
 
    * @param {class} Optional. The animation class to instantiate. Defaults to 
8723
 
    * YAHOO.util.Anim. Other options include YAHOO.util.Motion.
8724
 
    */
8725
 
    YAHOO.widget.ContainerEffect = function (overlay, attrIn, attrOut, targetElement, animClass) {
8726
 
 
8727
 
        if (!animClass) {
8728
 
            animClass = YAHOO.util.Anim;
8729
 
        }
8730
 
 
8731
 
        /**
8732
 
        * The overlay to animate
8733
 
        * @property overlay
8734
 
        * @type YAHOO.widget.Overlay
8735
 
        */
8736
 
        this.overlay = overlay;
8737
 
    
8738
 
        /**
8739
 
        * The animation attributes to use when transitioning into view
8740
 
        * @property attrIn
8741
 
        * @type Object
8742
 
        */
8743
 
        this.attrIn = attrIn;
8744
 
    
8745
 
        /**
8746
 
        * The animation attributes to use when transitioning out of view
8747
 
        * @property attrOut
8748
 
        * @type Object
8749
 
        */
8750
 
        this.attrOut = attrOut;
8751
 
    
8752
 
        /**
8753
 
        * The target element to be animated
8754
 
        * @property targetElement
8755
 
        * @type HTMLElement
8756
 
        */
8757
 
        this.targetElement = targetElement || overlay.element;
8758
 
    
8759
 
        /**
8760
 
        * The animation class to use for animating the overlay
8761
 
        * @property animClass
8762
 
        * @type class
8763
 
        */
8764
 
        this.animClass = animClass;
8765
 
    
8766
 
    };
8767
 
 
8768
 
 
8769
 
    var Dom = YAHOO.util.Dom,
8770
 
        CustomEvent = YAHOO.util.CustomEvent,
8771
 
        ContainerEffect = YAHOO.widget.ContainerEffect;
8772
 
 
8773
 
 
8774
 
    /**
8775
 
    * A pre-configured ContainerEffect instance that can be used for fading 
8776
 
    * an overlay in and out.
8777
 
    * @method FADE
8778
 
    * @static
8779
 
    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
8780
 
    * @param {Number} dur The duration of the animation
8781
 
    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
8782
 
    */
8783
 
    ContainerEffect.FADE = function (overlay, dur) {
8784
 
 
8785
 
        var Easing = YAHOO.util.Easing,
8786
 
            fin = {
8787
 
                attributes: {opacity:{from:0, to:1}},
8788
 
                duration: dur,
8789
 
                method: Easing.easeIn
8790
 
            },
8791
 
            fout = {
8792
 
                attributes: {opacity:{to:0}},
8793
 
                duration: dur,
8794
 
                method: Easing.easeOut
8795
 
            },
8796
 
            fade = new ContainerEffect(overlay, fin, fout, overlay.element);
8797
 
 
8798
 
        fade.handleUnderlayStart = function() {
8799
 
            var underlay = this.overlay.underlay;
8800
 
            if (underlay && YAHOO.env.ua.ie) {
8801
 
                var hasFilters = (underlay.filters && underlay.filters.length > 0);
8802
 
                if(hasFilters) {
8803
 
                    Dom.addClass(overlay.element, "yui-effect-fade");
8804
 
                }
8805
 
            }
8806
 
        };
8807
 
 
8808
 
        fade.handleUnderlayComplete = function() {
8809
 
            var underlay = this.overlay.underlay;
8810
 
            if (underlay && YAHOO.env.ua.ie) {
8811
 
                Dom.removeClass(overlay.element, "yui-effect-fade");
8812
 
            }
8813
 
        };
8814
 
 
8815
 
        fade.handleStartAnimateIn = function (type, args, obj) {
8816
 
            Dom.addClass(obj.overlay.element, "hide-select");
8817
 
 
8818
 
            if (!obj.overlay.underlay) {
8819
 
                obj.overlay.cfg.refireEvent("underlay");
8820
 
            }
8821
 
 
8822
 
            obj.handleUnderlayStart();
8823
 
 
8824
 
            obj.overlay._setDomVisibility(true);
8825
 
            Dom.setStyle(obj.overlay.element, "opacity", 0);
8826
 
        };
8827
 
 
8828
 
        fade.handleCompleteAnimateIn = function (type,args,obj) {
8829
 
            Dom.removeClass(obj.overlay.element, "hide-select");
8830
 
 
8831
 
            if (obj.overlay.element.style.filter) {
8832
 
                obj.overlay.element.style.filter = null;
8833
 
            }
8834
 
 
8835
 
            obj.handleUnderlayComplete();
8836
 
 
8837
 
            obj.overlay.cfg.refireEvent("iframe");
8838
 
            obj.animateInCompleteEvent.fire();
8839
 
        };
8840
 
 
8841
 
        fade.handleStartAnimateOut = function (type, args, obj) {
8842
 
            Dom.addClass(obj.overlay.element, "hide-select");
8843
 
            obj.handleUnderlayStart();
8844
 
        };
8845
 
 
8846
 
        fade.handleCompleteAnimateOut =  function (type, args, obj) {
8847
 
            Dom.removeClass(obj.overlay.element, "hide-select");
8848
 
            if (obj.overlay.element.style.filter) {
8849
 
                obj.overlay.element.style.filter = null;
8850
 
            }
8851
 
            obj.overlay._setDomVisibility(false);
8852
 
            Dom.setStyle(obj.overlay.element, "opacity", 1);
8853
 
 
8854
 
            obj.handleUnderlayComplete();
8855
 
 
8856
 
            obj.overlay.cfg.refireEvent("iframe");
8857
 
            obj.animateOutCompleteEvent.fire();
8858
 
        };
8859
 
 
8860
 
        fade.init();
8861
 
        return fade;
8862
 
    };
8863
 
    
8864
 
    
8865
 
    /**
8866
 
    * A pre-configured ContainerEffect instance that can be used for sliding an 
8867
 
    * overlay in and out.
8868
 
    * @method SLIDE
8869
 
    * @static
8870
 
    * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
8871
 
    * @param {Number} dur The duration of the animation
8872
 
    * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
8873
 
    */
8874
 
    ContainerEffect.SLIDE = function (overlay, dur) {
8875
 
        var Easing = YAHOO.util.Easing,
8876
 
 
8877
 
            x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
8878
 
            y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
8879
 
            clientWidth = Dom.getClientWidth(),
8880
 
            offsetWidth = overlay.element.offsetWidth,
8881
 
 
8882
 
            sin =  { 
8883
 
                attributes: { points: { to: [x, y] } },
8884
 
                duration: dur,
8885
 
                method: Easing.easeIn 
8886
 
            },
8887
 
 
8888
 
            sout = {
8889
 
                attributes: { points: { to: [(clientWidth + 25), y] } },
8890
 
                duration: dur,
8891
 
                method: Easing.easeOut 
8892
 
            },
8893
 
 
8894
 
            slide = new ContainerEffect(overlay, sin, sout, overlay.element, YAHOO.util.Motion);
8895
 
 
8896
 
        slide.handleStartAnimateIn = function (type,args,obj) {
8897
 
            obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
8898
 
            obj.overlay.element.style.top  = y + "px";
8899
 
        };
8900
 
 
8901
 
        slide.handleTweenAnimateIn = function (type, args, obj) {
8902
 
        
8903
 
            var pos = Dom.getXY(obj.overlay.element),
8904
 
                currentX = pos[0],
8905
 
                currentY = pos[1];
8906
 
        
8907
 
            if (Dom.getStyle(obj.overlay.element, "visibility") == 
8908
 
                "hidden" && currentX < x) {
8909
 
 
8910
 
                obj.overlay._setDomVisibility(true);
8911
 
 
8912
 
            }
8913
 
        
8914
 
            obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
8915
 
            obj.overlay.cfg.refireEvent("iframe");
8916
 
        };
8917
 
        
8918
 
        slide.handleCompleteAnimateIn = function (type, args, obj) {
8919
 
            obj.overlay.cfg.setProperty("xy", [x, y], true);
8920
 
            obj.startX = x;
8921
 
            obj.startY = y;
8922
 
            obj.overlay.cfg.refireEvent("iframe");
8923
 
            obj.animateInCompleteEvent.fire();
8924
 
        };
8925
 
        
8926
 
        slide.handleStartAnimateOut = function (type, args, obj) {
8927
 
    
8928
 
            var vw = Dom.getViewportWidth(),
8929
 
                pos = Dom.getXY(obj.overlay.element),
8930
 
                yso = pos[1];
8931
 
    
8932
 
            obj.animOut.attributes.points.to = [(vw + 25), yso];
8933
 
        };
8934
 
        
8935
 
        slide.handleTweenAnimateOut = function (type, args, obj) {
8936
 
    
8937
 
            var pos = Dom.getXY(obj.overlay.element),
8938
 
                xto = pos[0],
8939
 
                yto = pos[1];
8940
 
        
8941
 
            obj.overlay.cfg.setProperty("xy", [xto, yto], true);
8942
 
            obj.overlay.cfg.refireEvent("iframe");
8943
 
        };
8944
 
        
8945
 
        slide.handleCompleteAnimateOut = function (type, args, obj) {
8946
 
            obj.overlay._setDomVisibility(false);
8947
 
 
8948
 
            obj.overlay.cfg.setProperty("xy", [x, y]);
8949
 
            obj.animateOutCompleteEvent.fire();
8950
 
        };
8951
 
 
8952
 
        slide.init();
8953
 
        return slide;
8954
 
    };
8955
 
 
8956
 
    ContainerEffect.prototype = {
8957
 
 
8958
 
        /**
8959
 
        * Initializes the animation classes and events.
8960
 
        * @method init
8961
 
        */
8962
 
        init: function () {
8963
 
 
8964
 
            this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
8965
 
            this.beforeAnimateInEvent.signature = CustomEvent.LIST;
8966
 
            
8967
 
            this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
8968
 
            this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
8969
 
        
8970
 
            this.animateInCompleteEvent = this.createEvent("animateInComplete");
8971
 
            this.animateInCompleteEvent.signature = CustomEvent.LIST;
8972
 
        
8973
 
            this.animateOutCompleteEvent = 
8974
 
                this.createEvent("animateOutComplete");
8975
 
            this.animateOutCompleteEvent.signature = CustomEvent.LIST;
8976
 
        
8977
 
            this.animIn = new this.animClass(this.targetElement, 
8978
 
                this.attrIn.attributes, this.attrIn.duration, 
8979
 
                this.attrIn.method);
8980
 
 
8981
 
            this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
8982
 
            this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
8983
 
 
8984
 
            this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn, 
8985
 
                this);
8986
 
        
8987
 
            this.animOut = new this.animClass(this.targetElement, 
8988
 
                this.attrOut.attributes, this.attrOut.duration, 
8989
 
                this.attrOut.method);
8990
 
 
8991
 
            this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
8992
 
            this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
8993
 
            this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut, 
8994
 
                this);
8995
 
 
8996
 
        },
8997
 
        
8998
 
        /**
8999
 
        * Triggers the in-animation.
9000
 
        * @method animateIn
9001
 
        */
9002
 
        animateIn: function () {
9003
 
            this.beforeAnimateInEvent.fire();
9004
 
            this.animIn.animate();
9005
 
        },
9006
 
 
9007
 
        /**
9008
 
        * Triggers the out-animation.
9009
 
        * @method animateOut
9010
 
        */
9011
 
        animateOut: function () {
9012
 
            this.beforeAnimateOutEvent.fire();
9013
 
            this.animOut.animate();
9014
 
        },
9015
 
 
9016
 
        /**
9017
 
        * The default onStart handler for the in-animation.
9018
 
        * @method handleStartAnimateIn
9019
 
        * @param {String} type The CustomEvent type
9020
 
        * @param {Object[]} args The CustomEvent arguments
9021
 
        * @param {Object} obj The scope object
9022
 
        */
9023
 
        handleStartAnimateIn: function (type, args, obj) { },
9024
 
 
9025
 
        /**
9026
 
        * The default onTween handler for the in-animation.
9027
 
        * @method handleTweenAnimateIn
9028
 
        * @param {String} type The CustomEvent type
9029
 
        * @param {Object[]} args The CustomEvent arguments
9030
 
        * @param {Object} obj The scope object
9031
 
        */
9032
 
        handleTweenAnimateIn: function (type, args, obj) { },
9033
 
 
9034
 
        /**
9035
 
        * The default onComplete handler for the in-animation.
9036
 
        * @method handleCompleteAnimateIn
9037
 
        * @param {String} type The CustomEvent type
9038
 
        * @param {Object[]} args The CustomEvent arguments
9039
 
        * @param {Object} obj The scope object
9040
 
        */
9041
 
        handleCompleteAnimateIn: function (type, args, obj) { },
9042
 
 
9043
 
        /**
9044
 
        * The default onStart handler for the out-animation.
9045
 
        * @method handleStartAnimateOut
9046
 
        * @param {String} type The CustomEvent type
9047
 
        * @param {Object[]} args The CustomEvent arguments
9048
 
        * @param {Object} obj The scope object
9049
 
        */
9050
 
        handleStartAnimateOut: function (type, args, obj) { },
9051
 
 
9052
 
        /**
9053
 
        * The default onTween handler for the out-animation.
9054
 
        * @method handleTweenAnimateOut
9055
 
        * @param {String} type The CustomEvent type
9056
 
        * @param {Object[]} args The CustomEvent arguments
9057
 
        * @param {Object} obj The scope object
9058
 
        */
9059
 
        handleTweenAnimateOut: function (type, args, obj) { },
9060
 
 
9061
 
        /**
9062
 
        * The default onComplete handler for the out-animation.
9063
 
        * @method handleCompleteAnimateOut
9064
 
        * @param {String} type The CustomEvent type
9065
 
        * @param {Object[]} args The CustomEvent arguments
9066
 
        * @param {Object} obj The scope object
9067
 
        */
9068
 
        handleCompleteAnimateOut: function (type, args, obj) { },
9069
 
        
9070
 
        /**
9071
 
        * Returns a string representation of the object.
9072
 
        * @method toString
9073
 
        * @return {String} The string representation of the ContainerEffect
9074
 
        */
9075
 
        toString: function () {
9076
 
            var output = "ContainerEffect";
9077
 
            if (this.overlay) {
9078
 
                output += " [" + this.overlay.toString() + "]";
9079
 
            }
9080
 
            return output;
9081
 
        }
9082
 
    };
9083
 
 
9084
 
    YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
9085
 
 
9086
 
})();
9087
 
 
9088
 
YAHOO.register("container", YAHOO.widget.Module, {version: "2.7.0", build: "1799"});